2016-10-09 16 views
0

そこに:テンプレートクラスのメンバ関数の特殊化

次のコードの結果はどうなりますか?

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; 
} 

結果が異なっている:

MSVCでコンパイルさ
  1. 、G ++でコンパイル

    foo 
    foo 
    
  2. foo 
    foo<int> 
    

私は関係なく、コンパイラの第二の結果を取得したいと思います。達成するために私はさらに何をすべきですか?可能であれば、基礎となる基準や仕組みについて私に説明してください。ありがとうございました!

+2

「次のコードの結果」は、有効なC++コードが含まれていないため、foo.cxxのコンパイルエラーです。 –

+0

私は間違った型を変更しました:void Foo :: void print() - > void Foo :: print()もう一度、ありがとうございます。 –

+0

ヘッダーファイル内の特殊化を宣言するだけで、すべての翻訳単位で表示できるようになります。 'template <> void Foo :: print();'宣言をヘッダーファイルに追加してください。 –

答えて

1

プログラムに未定義の動作があります。

Foo<int>::print()の2つの実装 - 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

ありがとうございますが、リンクエラーがあります:_unresolved external symbols_ MSVCではg ++でOKです。 –

+0

@ドンギシン、私の最初の反応はおそらく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(); 
関連する問題