2016-10-09 129 views
0

there:模板类成员函数的专门化

以下代码的结果是什么?

foo.h中

#include <iostream> 

template<class _Tp> 
struct Foo 
{ 
    void print() { std::cout << "foo\n"; } 
}; 

foo.cxx

#include "foo.h" 

template<> 
void Foo<int>::print() 
{ 
    std::cout << "foo<int>\n"; 
} 

main.cxx

#include "foo.h" 

int main() 
{ 
    Foo<double>().print(); 
    Foo<int>().print(); 
    return 0; 
} 

结果是不同的:

  1. 时MSVC遵守,

    foo 
    foo 
    
  2. 当G ++编译,

    foo 
    foo<int> 
    

我想获得第二个结果无论编译器。我应该额外做些什么来实现?如果可能,你会给我一个关于基本标准或机制的解释。谢谢!

+2

“以下代码的结果”是foo.cxx中的编译错误,因为它不包含有效的C++代码。 –

+0

我改变了错误类型:void Foo :: void print() - > void Foo :: print()你会再次看到,谢谢。 –

+0

您只需要在头文件中声明特殊化,以便它在所有翻译单元中可见。添加一个'template <> void Foo :: print();'声明到头文件。 –

回答

1

你的程序有未定义的行为。

Foo<int>::print()有两种实现 - 从类模板定义和foo.cxx中的非内联定义获得的内联定义。编译器可以自由选择。

编译器不需要将其诊断为问题。他们中的很多人(显然包括g ++和MSVC)选择该路由来定义类模板及其成员函数。

为了确保两个编译器在foo.cxx中选择实现,请在foo.h中声明该函数。

#include <iostream> 

template<class _Tp> 
struct Foo 
{ 
    void print() { std::cout << "foo\n"; } 
}; 

template<> void Foo<int>::print(); 
+0

谢谢,但有一个链接错误:MSVC中的_unresolved external symbols_,因为它在g ++中是可以的。 –

+0

@ DongikShin,我的第一反应是可能是foo。cxx不是构建的一部分。如果foo.cxx是构建的一部分,我无法解释链接器错误。 –

0

这很有趣。我知道模板在编译时解释,而不是链接时间。所以,在我看来,专业化模板应该在每个cpp文件中实现。什么是你的g ++版本?

0

如果foo.h看起来像下面,两个编译器产生相同的结果。但我不知道为什么。

#include <iostream> 


template<class _Tp> 
struct Foo 
{ 
    void print(); 
}; 

template<class _Tp> 
void Foo<_Tp>::print() 
{ 
    std::cout << "foo\n"; 
} 

template<> void Foo<int>::print();