理论上编译器可以知道。
但是没有。 f1 是模板,不是函数,甚至不是类型,所以不能将它传递给任何模板参数列表。
虽然可以确定函数类型的第一个参数的类型。您可以尝试两次实例化模板,如果第一个参数的类型在两个模板实例之间不同,那么它就是模板化参数。当然,它通常不适用于每种模板(即,在某些模板中,两个不同模板参数的参数类型可能相同)。
我制作这个是为了我的使用(可能有更好的成熟变体——也许在 Boost 中?):
#include <functional>
template< typename F >
struct function_traits;
template< typename Result, typename... Params >
struct function_traits< Result( Params... ) >{
static const size_t paramCount = sizeof...( Params );
using result = Result;
template< size_t i >
using param = typename std::tuple_element< i, std::tuple< Params... > >::type;
};
template< typename Result, typename... Params >
struct function_traits< Result(*)( Params... ) >
: public function_traits< Result( Params... ) > {
};
template< typename Result, typename... Params >
struct function_traits< std::function< Result( Params... ) > >
: public function_traits< Result( Params... ) >{
};
// shortcuts to help avoid the weird "typename" and "template" disambiguators
template< typename T >
using function_result_t = typename function_traits<T>::result;
template< typename T, size_t i >
using function_param_t = typename function_traits<T>::template param<i>; // lol, that's evil syntax
所以对于这种情况,我会像这样使用它:
using first_param_type_1st_try = function_param_t< f1<int>, 0 >;
using first_param_type_2nd_try = function_param_t< f1<unsigned>, 0 >;
bool is_first_param_probably_templated
= !std::is_same_v<first_param_type_1st_try, first_param_type_2nd_try>;
虽然这有一半是没有意义的,因为你知道非模板函数的第一个参数是非模板的。而且您必须将任何模板名称实例化为类型名称。
您可以使用 SFINAE 并将函数包装在测试模板中来解决其中的一些问题。再一次,它会很丑陋,而且通常不能正常工作。