我创建了两个简单的函数来获取模板参数和一个定义类型的空结构:
//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;
}
Run Code Online (Sandbox Code Playgroud)
参数类型应用于struct S以获取引用.我用一些整数值调用它们但编译器无法推断出参数:
int main()
{
char c=6;
int d=7;
int res = temp(c);
int res2 = temp2(d,7);
}
Run Code Online (Sandbox Code Playgroud)
错误1错误C2783:'临时(S ::类型)':无法推断'A'的模板参数
错误2错误C2783:'B temp2(S :: type,B)':无法推断'A'的模板参数
为什么会这样?是否很难看到模板参数是char和int值?
Lea*_*elo 29
与第一个注意事项一样,当您提及从属名称时,将使用typename 名称.所以你在这里不需要它.
template <class T>
struct S
{
typedef T& type;
};
Run Code Online (Sandbox Code Playgroud)
关于模板实例化,问题在于typename S<A>::type表征A 的非弱化上下文.当模板参数仅用于非弱化上下文(函数中的A的情况)时,不考虑模板参数推导.详情见C++标准(2003)第14.8.2.4节.
要使您的呼叫起作用,您需要明确指定类型:
temp<char>(c);
Run Code Online (Sandbox Code Playgroud)
它看起来像非弱化的上下文.根据C++标准14.8.2.4/4:
非受限的上下文是:
- 使用qualified-id 指定的类型的嵌套名称说明符.
- 一种类型,它是一个template-id,其中一个或多个template-arguments是一个引用模板参数的表达式.
如果以包含非损坏上下文的方式指定类型名称,则包含该类型名称的所有类型也都是非限定的.但是,复合类型可以包括推导类型和非推导类型.[ 实施例:如果一个类型被指定为
A<T>::B<T2>,两者T和T2是nondeduced.同样地,如果一个类型被指定为A<I+J>::X<T>,I,J,和T是nondeduced.如果将类型指定为void f(typename A<T>::B, A<T>),则TinA<T>::B为nondeuced但TinA<T>推导出.]
扣除在前进方向:
template <class T> void f(T);
f(2); // can deduce int from T
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
它不向后退(你的例子):
template <class A> void g(typename S<A>::type);
Run Code Online (Sandbox Code Playgroud)
是否很难看到模板参数是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;
...
}
Run Code Online (Sandbox Code Playgroud)
使用你最喜欢的静态断言库(Boost有两个).