Naw*_*waz 3 c++ standards templates iso
如果我们有这个功能模板,
template<typename T>
void f(T param) {}
Run Code Online (Sandbox Code Playgroud)
然后我们可以通过以下方式调用它,
int i=0;
f<int>(i);//T=int : no need to deduce T
f(i); //T=int : deduced T from the function argument!
//likewise
sample s;
f(s); //T=sample : deduced T from the function argument!
Run Code Online (Sandbox Code Playgroud)
现在考虑上面函数模板的这个变体,
template<typename TArg, typename TBody>
void g(TArg param)
{
TBody v=param.member;
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我们写,编译器可以推断出模板参数吗?
sample s;
g(s); //TArg=sample, TBody=int??
Run Code Online (Sandbox Code Playgroud)
假设sample定义为,
struct sample
{
int member;
};
Run Code Online (Sandbox Code Playgroud)
基本上有两个问题:
我想知道你对这种演绎的看法.
编辑:
顺便说一下,如果我们编写这段代码,GCC能够推导出函数参数:
template<typename T>
void h(T p)
{
cout << "g() " << p << endl;
return;
}
template<typename T>
void g(T p)
{
h(p.member); //if here GCC can deduce T for h(), then why not TBody in the previous example?
return;
}
Run Code Online (Sandbox Code Playgroud)
此示例的工作演示:http://www.ideone.com/cvXEA
上一个示例的工作演示不起作用:http://www.ideone.com/UX038
您可能已经得出结论,编译器不会TBody通过检查类型来推断sample.member.这将为模板推导算法增加另一层复杂性.
模板匹配算法仅考虑函数签名,而不考虑它们的主体.虽然不经常使用,但简单地声明模板化函数而不提供正文是完全合法的:
template <typename T> void f(T param);
Run Code Online (Sandbox Code Playgroud)
这满足了编译器.为了满足链接器,您当然还必须在某处定义函数体,并确保已提供所有必需的实例化.但功能身体并没有一定要与模板功能的客户端代码可见,只要所需的实例都可以在链接时.正文必须显式实例化该函数,例如:
template <> void f(int param);
Run Code Online (Sandbox Code Playgroud)
但这只是部分适用于您的问题,因为您可以想象如下所示的场景,其中第二个参数可以从提供的默认参数中推导出来,并且不会编译:
template<typename TArg, typename TBody>
void g(TArg param, TBody body = param.member); // won't deduce TBody from TArg
Run Code Online (Sandbox Code Playgroud)
模板匹配算法仅考虑实际类型,而不考虑类或结构的任何潜在嵌套成员类型.这会增加另一层次的复杂性,显然被认为过于复杂.算法应该停在哪里?是否还要考虑成员等等?
此外,它不是必需的,因为还有其他方法可以实现相同的意图,如下例所示.
没有什么能阻止你写作:
struct sample
{
typedef int MemberType;
MemberType member;
};
template<typename TArg>
void g(TArg param)
{
typename TArg::MemberType v = param.member;
}
sample s = { 0 };
g(s);
Run Code Online (Sandbox Code Playgroud)
为了获得同样的效果.
关于你在编辑后添加的样本:虽然它似乎h(p.member)取决于结构的成员,因此模板匹配算法应该失败,但它不会因为你使它分为两步:
g(s);,编译器会查找带有类型参数的任何函数sample(模板化或不模板化!).在你的情况下,最好的匹配是void g(T p).此时,编译器甚至还没有看过机身g(T p)呢!.g(T p)专门用于的实例T: sample.所以当它看到h(p.member)它知道它p.member是类型的时候int,并且会尝试找到一个h()带有类型参数的函数int.您的模板功能h(T p)证明是最佳匹配.请注意,如果您已经写过(请注意NOT_A_member):
template<typename T>
void g(T p)
{
h(p.NOT_A_member);
return;
}
Run Code Online (Sandbox Code Playgroud)
然后编译器仍会g()在第1阶段考虑有效匹配.然后,当结果sample没有调用成员时,会出现错误NOT_A_member.