这些天我在用SFINAE做实验,还有一些让我感到困惑。为什么my_type_a
不能在my_function
的实例化中推导出来?SFINAE和模板函数实例化:为什么在使用具有SFINAE的类型的函数参数中使用模板参数时不能推导出来?
class my_type_a {};
template <typename T>
class my_common_type {
public:
constexpr static const bool valid = false;
};
template <>
class my_common_type<my_type_a> {
public:
constexpr static const bool valid = true;
using type = my_type_a;
};
template <typename T> using my_common_type_t = typename my_common_type<T>::type;
template <typename T, typename V>
void my_function(my_common_type_t<T> my_cvalue, V my_value) {}
int main(void) {
my_function(my_type_a(), 1.0);
}
G ++给了我这样的:
/home/flisboac/test-template-template-arg-subst.cpp: In function ‘int main()’:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: error: no matching function for call to ‘my_function(my_type_a, double)’
my_function(my_type_a(), 1.0);
^
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: candidate: template<class T, class V> void my_function(my_common_type_t<T>, V)
void my_function(my_common_type_t<T> my_type, V my_value) {}
^~~~~~~~~~~
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: template argument deduction/substitution failed:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: note: couldn't deduce template parameter ‘T’
my_function(my_type_a(), 1.0);
^
我所期待的是,在调用my_function
当我在main
一样,T
会被推断为函数的第一个参数的类型,以及该类型将用于函数的实例化。但似乎my_common_type_t<T>
是函数之前实例化,但即使如此,中my_cvalue
类型将成为my_type_a
反正,所以我不明白为什么这是行不通的......
是否有不同的方式来做到这一点?我应该避免两个(或更多)级别的模板间接?
在'my_common_type :: type'中,'T'在[非推导的上下文](http://en.cppreference.com/w/cpp/language/template_argument_deduction#Non-deduced_contexts)中。你希望编译器用每个可能的类型'T'实例化'my_common_type',希望其中的一个'my_common_type :: type'出来与'my_type_a'兼容;或者参与定理证明练习以尝试并通过分析找到这种类型。编译器不会。 –
@Igor我明白规则1(来自您提供的链接)当然符合我的例子。但是,为什么不清楚'T'不一定是'my_type_a'?如果'my_common_type'在实例化'my_function'之前被实例化,那么类型可能是'my_type_a'或者什么也不是(因此函数将通过SFINAE消除)。如果在编译期间或之后实例化,编译器会将'my_common_type '的信息作为候选(因此,'T = my_type_a'),是不是? –
*“为什么不清楚”*这是我说的定理证明练习。这里的“清除”意味着“可以从现有事实中证明”。也许它可以 - 但编译器不需要拥有这种推理引擎。 –