Как написать трейт типа, который проверяет, совместимы ли типы кортежей с аргументами функции

Я пытаюсь написать черту типа, которая проверяет, совместимы ли типы, хранящиеся в кортеже, с аргументами данного вызываемого объекта.

В настоящее время у меня есть «почти рабочий» код, показанный ниже. Однако статическое утверждение терпит неудачу в последнем выражении с вызываемым объектом, который ожидает ссылочные параметры (например, [](int&, std::string&){}), я действительно не понимаю, почему это терпит неудачу. И как написать черту, которая является инклюзивной для этого типа?

#include <type_traits>
#include <tuple>
#include <string>

template<typename, typename>
struct is_callable_with_tuple: std::false_type {};

template<typename Func, template<typename...> class Tuple, typename... Args>
struct is_callable_with_tuple<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {};

template<typename Func, typename Args>
constexpr bool is_callable_with_tuple_v = is_callable_with_tuple<Func, Args>::value;

int main() {    
    static_assert(is_callable_with_tuple_v<decltype([](int, std::string){}), std::tuple<int, std::string>>); // OK
    static_assert(is_callable_with_tuple_v<decltype([](const int&, const std::string&){}), std::tuple<int, std::string>>); // OK
    static_assert(is_callable_with_tuple_v<decltype([](int&, std::string&){}), std::tuple<int, std::string>>); // Fails
}

Только что обнаружил, что кортеж с сохраненными ссылками исправляет утверждение: но это не совсем то, что я хочу

mennok 22.04.2022 22:17

Кортеж — отвлекающий маневр. std::is_invocable_v<void(int&), int> есть false, потому что нет смысла определять его каким-либо другим способом.

n. 1.8e9-where's-my-share m. 22.04.2022 22:19
stackoverflow.com/questions/64883044/…
Igor R. 22.04.2022 22:20

Чего вы пытаетесь достичь с помощью этой черты? Код на самом деле правильный, decltype([](int&, std::string&){}) нельзя вызывать с int, std::string, потому что это потребует привязки rvalue к неконстантной ссылке lvalue, что не разрешено.

Quxflux 22.04.2022 22:27
3 метода стилизации элементов HTML
3 метода стилизации элементов HTML
Когда дело доходит до применения какого-либо стиля к нашему HTML, существует три подхода: встроенный, внутренний и внешний. Предпочтительным обычно...
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
1
4
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете немного изменить свою черту:

template<typename Func, 
         template<typename...> class Tuple, 
         typename... Args>
struct is_callable_with_tuple<Func, Tuple<Args...>>: 
    std::is_invocable<Func, Args&...> {}; // <--- note &

Или нет, в зависимости от того, как именно вы планируете его использовать. Если ваш кортеж всегда является lvalue, вероятно, все в порядке. Если нет, то вы можете специализировать его для типа кортежа lvalue-reference:

template<typename Func, 
         template<typename...> class Tuple, 
         typename... Args>
struct is_callable_with_tuple<Func, Tuple<Args...>&>:  // <--- note & here
    std::is_invocable<Func, Args&...> {}; // <--- and also here

template<typename Func, 
         template<typename...> class Tuple, 
         typename... Args>
struct is_callable_with_tuple<Func, Tuple<Args...>>:  // <--- note NO & here
    std::is_invocable<Func, Args...> {}; // <--- and also here

и используйте его так:

is_callable_with_tuple<decltype(myfunc), decltype((mytuple))> // note double parentheses

Спасибо, это работает для меня. Однако я не совсем понимаю, зачем нужны двойные скобки во втором решении. Можете ли вы объяснить, почему? Редактировать: Ах, немного погуглил, насколько я понимаю (tuple) - это выражение lvalue, которое заставит его вызывать первый trait .

mennok 23.04.2022 07:50

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