Аргументы функции шаблона с переменным числом аргументов не принимаются

Следующий код не будет собран, будем признательны за любые отзывы о причине.

void bar(std::string str, int& a, int& b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

void run()
{
    int a = 3;
    int b = 5;
    foo<std::string, int&, int&>(bar, a, b);
}

Это модифицированная реализация первого решения, предложенного в этом ТАК-ответе.

IDE выдает следующую ошибку при вызове строки foo:

Шаблон C++<class T, class... Args> void foo(std::function<void (T, Args...)> fcn, Args ...args)

ни один экземпляр шаблона функции «foo» не соответствует списку аргументов
типы аргументов:
(void (std::string str, int &a, int &b), int, int)

Протестировано отдельно, кажется, что передача аргумента fcn с аргументами шаблона — это нормально. Проблема, по-видимому, заключается в передаче аргумента функции, где функция может принимать аргументы шаблона с переменным числом аргументов.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
59
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Функция (указатель) не является std::function, поэтому не работает для вывода.

В этом контексте вы можете сделать Ts... невыводимым.

template<typename T, typename ... Args>
void foo(std::function<void(T, std::type_identity_t<Args>...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

Демо

или отбросьте std::function полностью

template<typename T, typename F, typename ... Args>
requires (std::is_invocable<F, T, Args...>::value)
void foo(F fcn, Args&& ... args)
{
    // Some code that calls fcn
}

Демо

Спасибо! Есть ли обходной путь, который не требует С++ 20? Кажется, type_identity был добавлен в C++20.

zack 29.08.2024 14:05

То же самое справедливо и для std::is_invocable. Оба ответа приветствуются, несмотря ни на что.

zack 29.08.2024 14:15

Но вычет не происходит, если указаны аргументы шаблона.

David G 29.08.2024 16:54
std::type_identity можно легко реализовать повторно.
Jarod42 29.08.2024 17:11

Использование requires можно заменить на auto foo(F f, Args&&... args) -> decltype(f(std::declval<T>(), std::forward<Ts>(args)...), void())

Jarod42 29.08.2024 17:13

@DavidG: Мы указываем начало, мы не можем сказать, что остановка пакета, т. е. с template <typename... Ts> void bar(std::tuple<Ts...>); bar<int>(std::tuple<int, char, float>{}) действительна.

Jarod42 29.08.2024 17:17
Ответ принят как подходящий
  • и когда я его удалил, ошибки не было
#include <iostream>
#include <functional> 

void bar(std::string str, int a, int b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}


int main() {
    std::function<void(std::string, int, int)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, a, b);
    return 0;
}
  • Если необходимо использовать вызов по ссылке, я попробовал, указав прямой адрес, и в этом случае тоже сработало.
#include <iostream>
#include <functional> 

void bar(std::string str, int* a, int* b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}


int main() {
    std::function<void(std::string, int*, int*)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, &a, &b);
    return 0;
}

Отлично, спасибо. Линия func_1 очень помогает.

zack 29.08.2024 15:00

Спасибо всем. Судя по ответу от Серкана, кажется, работает следующее.

#include <iostream>
#include <functional> 

void bar(std::string str, int& a, int& b)
{
}

template<typename T, typename ... Args>
void foo(std::function<void(T, Args...)> fcn, Args ... args)
{
    // Some code that calls fcn
}

int main() {
    std::function<void(std::string, std::reference_wrapper<int>, std::reference_wrapper<int>)> func_1 = bar;
    int a = 3;
    int b = 5;
    foo(func_1, std::ref(a), std::ref(b));
    foo((std::function<void(std::string, std::reference_wrapper<int>, std::reference_wrapper<int>)>)bar, std::ref(a), std::ref(b));
    return 0;
}

Я проведу еще тесты, возможно, еще потребуются некоторые изменения.

Другие вопросы по теме

Специализация шаблона на C++ с использованием Enable_if
Специализация шаблона C++ STD внутри другого пространства имен
Почему определение оператора = (а не объявление) должно быть написано, когда подходящий шаблон легко доступен
Использование SFINAE в конструкторе, чтобы проверить, существует ли конструктор типа члена
Использование if-constexpr и концепций для обнаружения экземпляра определенного типа расширенной политики
Почему квалификатор const игнорируется при применении к выведенной ссылке Lvalue в C++?
Создание декартова произведения на основе аргумента шаблона целочисленного диапазона
Почему выведение std::call_once не удалось и возникла ошибка «не удалось вывести параметр шаблона ‘_Callable’»
Невозможно получить доступ к специализации класса шаблона через универсальную ссылку
Вывести класс шаблона с уменьшенным количеством параметров шаблона

Похожие вопросы

Специализация шаблона на C++ с использованием Enable_if
Почему C++ выбирает перегрузку базового класса при использовании указателя на функцию-член производного класса?
Почему возникает состояние гонки, когда аппаратное обеспечение обеспечивает согласованность
Производный виджет Gtk::DrawingArea загружается из файла компоновщика Glade неправильно
Ошибка нарушения прав доступа при многопоточном сканировании диска с помощью C++
Является ли замена всех const std::string & на std::string_view хорошим выбором?
C++ Неопределенное поведение при использовании переинтерпретации приведения
Как получить понятное имя, принадлежащее дескриптору HMONITOR в Windows?
Цикл while в C++ завершается сбоем, если целое число содержит более 10 цифр
Какова точная цитата из стандарта C++, в которой говорится, что ошибка вывода типа при выведении аргумента шаблона не является ошибкой (SFINAE)?