【发布时间】:2017-07-31 02:27:43
【问题描述】:
这些天我在试验 SFINAE,有些事情让我很困惑。为什么my_type_a不能在my_function的实例化中推导出来?
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);
^
我所期望的是,当像在main 中那样调用my_function 时,T 将被推导出为函数的第一个参数的类型,并且该类型将用于函数的实例化。但似乎my_common_type_t<T> 在函数之前被实例化,但即便如此,my_cvalue 的类型无论如何都会变成my_type_a,所以我不明白为什么这不起作用......
有其他方法可以做到这一点吗?我应该避免两个(或更多)级别的模板间接吗?
【问题讨论】:
-
在
my_common_type<T>::type中,T在non-deduced context 中。您希望编译器用每种可能的类型T实例化my_common_type,希望对于其中一个,my_common_type<T>::type与my_type_a兼容;或者进行定理证明练习以尝试分析地找到这样的类型。编译器两者都不做。 -
@Igor 我了解规则 1(来自您提供的链接)当然与我的示例相匹配。但是,为什么不清楚
T不一定是my_type_a?如果在实例化my_function之前实例化了my_common_type<T>,则类型将是my_type_a或什么都没有(因此该函数将通过 SFINAE 消除)。如果它在期间或之后被实例化,编译器会将my_common_type<my_type_a>的信息作为候选(并且因此,T = my_type_a),不是吗? -
“为什么不清楚” 这就是我所说的定理证明练习。这里的“清楚”是指“可以从现有的事实证明”。也许它可以——但编译器不需要拥有这种推理引擎。
-
我认为可以从呼叫站点获得信息。但也许我从错误的角度考虑事情。我想我理解这里的问题,但我很难想出一个明确的答案。
my_function在参数my_cvalue中接收my_common_type<T>::type类型的值,而T不会在其他任何地方使用。我传递给函数的是my_type_a的值,这是具体的。my_common_type<T>::type仍然未知,因为::type依赖于模板替换,而模板替换又依赖于T,目前尚不清楚。
标签: c++ templates c++14 template-argument-deduction