ls.*_*ls. 10 c++ templates template-specialization
我已经阅读了为什么不专业化功能模板,经过一些实验,我发现了一件有趣的事情.这里去main.cxx:
// main.cxx
#include <iostream>
// Declarations
/*
template<class T>
void foo(T);
template<>
void foo(int*);
template<class T>
void foo(T*);
*/
// Definition and specification
template<class T>
void foo(T x)
{
std::cout << "T version." << std::endl;
}
template<>
void foo(int *i)
{
std::cout << "int* version." << std::endl;
}
template<class T>
void foo(T *x)
{
std::cout << "T* version" << std::endl;
}
int main(int argc, char** argv)
{
int *p;
foo(p);
}
Run Code Online (Sandbox Code Playgroud)
有趣的是:如果我留下声明部分进行评论,那么行为就像文章所说的那样,即如果int*version的定义在其定义之前,副本和经文之前,将使用T*版本.但是,如果取消注释声明块,则无论我在定义或声明中使用哪个顺序,都只会调用int*version.我的问题是这个声明如何影响决议?
有任何想法吗?我在x86_64-redhat-linux上使用g ++ 4.2.2
编辑:看到AProgrammer的答案后简化这个问题
APr*_*mer 10
分发源成三个文件搞乱事项:预处理使一个编译单元和行为只是取决于CU的内容,而不是在它被多少个文件分发.
在这种情况下,我认为你很惊讶
#include <iostream>
template<class T> void foo(T); // A
template<> void foo(int*); // 1
template<class T> void foo(T*); // B
template<class T> void foo(T x)
{ std::cout << "T version." << std::endl; }
template<> void foo(int *i) // 2
{ std::cout << "int* version." << std::endl; }
template<class T> void foo(T *x)
{ std::cout << "T* version" << std::endl; }
int main(int argc, char** argv) {
int *p;
foo(p);
}
Run Code Online (Sandbox Code Playgroud)
你得到int* version.这是预期的行为.虽然(1)确实声明了专业化template <typename T> void foo(T),但(2)不是该专业化的定义.(2)定义并声明template<class T> void foo(T*);其中的特化,然后调用main().如果您在声明和定义的任何内容中给出三个定义之前的三个声明,就会发生这种情况.定义(2)将始终看到声明template<class T> void foo(T*);,因此是它的专业化.
当声明或定义函数模板的特化时,它可以是几个函数模板的特化(比如这里(2)可以是两个重载A和B的特化,它们只需要声明),它就是一个专业化的"更专业化"的一个.您可以在标准17.5.5.2节中看到"更专业"的精确定义,但很容易看出B对于(2)来说是比A更好的匹配,因此(2)是(B)的特化.(1)宣布(A)的专业化,因为当宣布(1)时,(B)尚未被看见.如果你想在(B)之后给出(1)的定义,你必须写
template <> void foo<int*>(int*) // definition for (1)
{ std::cout << "foo<int*>(int*)\n"; }
Run Code Online (Sandbox Code Playgroud)
在定义(2)时你也可以是明确的:
template<> void foo<int>(int *i) // 2 alternate
{ std::cout << "int* version." << std::endl; }
Run Code Online (Sandbox Code Playgroud)
(但显然在同一个CU中给出(2)和这个替代版本会给你一个错误).
调用函数时也可以显式:
foo(p); // call (2)
foo<int>(p); // call (2)
foo<int*>(p); // call (1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
176 次 |
| 最近记录: |