如何编写检查元组类型是否与函数参数兼容的类型特征

How to write a type trait that checks if tuple types are compatible with function arguments

我正在尝试编写一个类型特征来检查存储在元组中的类型是否与给定可调用对象的参数兼容。

目前,我有 'almost working' 代码,如下所示。但是,静态断言在最后一个语句中失败,带有一个需要引用参数的可调用对象(例如 [](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
}

您可能想要稍微修改一下您的特质:

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

或不,取决于您打算如何使用它。如果您的元组始终是左值,则可能没问题。如果没有,那么您可能希望将其专门化为 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