2016-09-06 7 views
15

は、私は私のコードは、このように構成されているとし:この場合、テンプレートの特殊化をcppファイルに書き込むことはできますか?

  • header1.h

    template <class T, template<class> class C> 
    struct metafunction { 
        using type = typename C<T>::type; 
    }; 
    
    inline namespace msn { 
        template <class T> struct implementation; 
    } 
    
    // uses the *implementation* not defined in the header! 
    template <class T> 
    struct use_case { 
        using type = typename metafunction<T, implementation>::type; 
    }; 
    
  • cpp1.cpp

    #include <header1.h> 
    
    // I'll only need this in this compilation unit, so the 
    // question is: "Is this a good place to define it?" 
    template <> 
    struct implementation<int> { 
        using type = int; 
    }; 
    
    int main() { 
        using tt = int; 
        // is this point of instantiation OK due to 
        // the existence of a specialization in the same cpp file? 
        using tt = use_case<int>::type; 
    
        tt var; 
        (void)var; 
    } 
    

私の前提は、私​​が唯一のよということです私はリンカーの問題に対処する必要はありませんので、cppファイル内の特定の専門分野を使用してください。 これは、cpp2.cppファイル(header1.hを含む)では使用できず、use_case<int>を使用するか、ODRに違反するimplementation<int>を再定義しようとしています。だから、私はこのコードがlinear form(すべてが1つのcppファイルに適合する順序で入れられているバージョン)に類似しているかどうかを尋ねています。

+0

この目的で 'extern'テンプレートを使うことができます。 –

+0

@KerrekSB私はインラインネームスペースで持ち去られました。私がC++ 11を持っていないとすれば、与えられたコードが悪いですか? –

+0

どのような詳細をお探しですか? – Barry

答えて

8

はい、同じ翻訳単位内でのみ使用されている限り、これは正しい形式です。

#includeの効果は、参照されたファイルがそのまま翻訳単位に挿入されているかのようになります。

これは#includeです。このことから

、我々はいくつかの結論を出すことができます。

すべてのC++変換ユニットは、単一の仮想ファイルです。

したがって、整形式翻訳単位のすべての専門用語は、それを定義する同じ翻訳単位で参照されます。

Q.E.D.

0

一般に、私は@サムの答えに同意しますが、私はそのような特殊化はローカルタイプに対してのみ行います。 「ローカルタイプ」とは、この翻訳ユニットでのみアクセス可能なタイプを意味します。この.cppファイルでのみ定義されているクラス(匿名名前空間内)。

なぜなら、このように特殊化より幅広くアクセスできるタイプで特殊化すると、ODR(One Definition Rule)違反が非常に発生しやすくなります。将来別のコードが同じタイプのテンプレートを使用し始めると、同じではないテンプレートの2つのインスタンス化が得られることは容易に理解できます(1つは特殊化を使用し、もう1つはそれなし)。このような場合、これはODR違反であり、その動作は定義されていません。

だからint「ローカル」の専門分野には適していません。

特殊化を.cppファイルにローカルに保存したい場合は、追加のタグをテンプレートパラメータに追加する必要があります(元のテンプレートに別のパラメータを追加する必要があります)。このタグはローカルタイプ(例えば、このファイルの匿名名前空間内にstruct private_tag{};を定義し、それをスペシャライゼーションで使用する)。この方法では、特殊化には他のTUで使用できない固有の型があるため、ODR違反から安全です。

関連する問題