为什么模板论证扣除在这里不起作用?
我创build了两个获取模板参数的简单函数和一个定义types的空结构:
//S<T>::type results in T& template <class T> struct S { typedef typename T& type; }; //Example 1: get one parameter by reference and return it by value template <class A> A temp(typename S<A>::type a1) { return a1; } //Example 2: get two parameters by reference, perform the sum and return it template <class A, class B> B temp2(typename S<A>::type a1, B a2)//typename struct S<B>::type a2) { return a1 + a2; }
参数types被应用到结构S以获得引用。 我用一些整数值调用它们,但是编译器无法推导出这些参数:
int main() { char c=6; int d=7; int res = temp(c); int res2 = temp2(d,7); }
错误1错误C2783:'临时(S ::types)':无法推断出'A'的模板参数
错误2错误C2783:'B temp2(S :: type,B)':无法推断出'A'的模板参数
为什么发生这种情况? 难以看出模板参数是char和int值吗?
就像第一个注意事项一样,当您提到一个依赖名称时,使用了typename name。 所以你不需要这里
template <class T> struct S { typedef T& type; };
关于模板实例化,问题在于typename S<A>::type
表示A的非诱致上下文。当一个模板参数仅用于非诱致上下文(函数A中的情况)时,不考虑模板论证扣除。 细节在C ++标准(2003)的14.8.2.4节。
要使您的通话有效,您需要明确指定types:
temp<char>(c);
这看起来像非诱惑的上下文。 根据C ++标准14.8.2.4/4:
非诱骗的情况是:
- 使用限定标识 指定的types的嵌套名称说明符。
- 一个types,它是一个template-id ,其中一个或多个模板参数是引用模板参数的expression式。
当一个types名称被指定的方式包含一个nondeduced上下文时,包含该types名称的所有types也都是非导出的。 但是,复合types可以包括推导types和非推导types。 [ 例如 :如果一个types被指定为
A<T>::B<T2>
,那么T
和T2
都是非导出的。 同样,如果一个types被指定为A<I+J>::X<T>
,则I
,J
和T
是非导致的。 如果一个types被指定为void f(typename A<T>::B, A<T>)
,则A<T>::B
中的T
是非导致的,但是推导出A<T>
中A<T>
]
扣除工作的前进方向:
template <class T> void f(T); f(2); // can deduce int from T
为什么发生这种情况?
它不能在反向工作(你的例子):
template <class A> void g(typename S<A>::type);
难以看出模板参数是char和int值吗?
模板扣除可以做一些神奇的(图灵完成)的东西,但我不认为这是其中之一。
你可以使用像(未经testing)的东西:
template <class SA> void h(SA a1) { STATIC_ASSERT(same_type<SA, S<A>::type>::value); typedef typename SA::type A; ... }
使用你最喜欢的静态断言库(Boost有两个)。