我创建了两个简单的函数来获取模板参数和一个定义类型的空结构:
//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;
}
参数类型应用于struct S以获取引用。我用一些整数值调用它们但编译器无法推断出参数:
int main()
{
char c=6;
int d=7;
int res = temp(c);
int res2 = temp2(d,7);
}
错误1错误C2783:'A temp(S :: type)':无法演绎 'A'的模板参数
错误2错误C2783:'B temp2(S :: type,B)':不能 推导出'A'的模板参数
为什么会这样?是否很难看到模板参数是 char 和 int 值?
答案 0 :(得分:29)
正如首先注意的那样,当您提及依赖名称时,会使用typename名称。所以你在这里不需要它。
template <class T>
struct S
{
typedef T& type;
};
关于模板实例化,问题是typename S<A>::type
表征A的 nondeduced 上下文。当模板参数仅用于非弱化上下文时(函数中A的情况) )模板参数推导没有考虑到它。详情见C ++标准(2003)第14.8.2.4节。
要使您的通话有效,您需要明确指定类型:
temp<char>(c);
答案 1 :(得分:8)
看起来像非弱化的上下文。根据C ++标准14.8.2.4/4:
非弱势语境是:
- 使用 qualified-id 指定的类型的嵌套名称说明符。
- template-id 的类型,其中一个或多个 template-arguments 是一个引用 template-parameter
如果以包含非弱化上下文的方式指定类型名称,则包含该类型名称的所有类型也不会受到限制。但是,复合类型可以包括推导类型和非推导类型。 [示例:如果类型指定为
A<T>::B<T2>
,则T
和T2
都不受限制。同样,如果某个类型指定为A<I+J>::X<T>
,则I
,J
和T
不会被限制。如果将类型指定为void f(typename A<T>::B, A<T>)
,则T
中的A<T>::B
未受到限制,但推导出T
中的A<T>
。 ]
答案 2 :(得分:5)
扣除工作向前发展:
template <class T> void f(T);
f(2); // can deduce int from T
为什么会这样?
它不向后退(你的例子):
template <class A> void g(typename S<A>::type);
难道很难看出模板参数是char和int值吗?
模板演绎可以做一些神奇的(Turing-complete)事情,但我不认为这是其中之一。
您可能会使用类似(未经测试)的内容:
template <class SA> void h(SA a1)
{
STATIC_ASSERT(same_type<SA, S<A>::type>::value);
typedef typename SA::type A;
...
}
使用您喜欢的静态断言库(Boost有两个)。