7

ヘッダー ファイルで変数テンプレートを前方宣言し、実際のインスタンス化を別のコンパイル ユニットで行いたいと考えています。

私は、C++14 の変数テンプレートは静的クラス変数と非常によく似ていると考えるようになりました。残念ながら、これはまったく当てはまらないようで、変数テンプレートを前方宣言することを妨げています。

template <typename T> struct Variable {
    static int variable;
};

template <typename T> 
extern int variable;

int main() {
    (void) Variable<char>::variable;
    // (void) variable<char>;                   // <-- line 10
}

template <> int Variable<char>::variable = 42;
template <> int variable<char> = 23;

上記のコード サンプルは、GCC でそのままコンパイルおよび実行されます。ただし、10 行目のコメントを外すと、コンパイル時にエラーが発生します。

specialization of 'variable<char>' after instantiation
    template <> int variable<char> = 23;
                     ^
4

2 に答える 2

2

あなたは正しい軌道に乗っていると思います。

秘訣は次のとおりです。どの翻訳単位でも、専門化の前にテンプレートをインスタンス化しないでください。

例えば:

// test.h
#ifndef TEST_H
#define TEST_H

template <typename T> 
extern int variable;

template <> extern int variable<char>;
template <> extern int variable<int>;

#endif // TEST_H

それで:

// test2.cpp
#include "test.h"

template <> int variable<char> = 23;
template <> int variable<int> = 24;

そして最後に:

// test.cpp
#include "test.h"
#include <iostream>

int
main()
{
    std::cout << variable<char> << '\n';
    std::cout << variable<int> << '\n';
}

私にとって、これは次の出力を出力します:

23
24

アップデート

TC は以下のコメントで、特殊化は最初に使用する前に宣言する必要があると指摘しているので、上記の「test.h」を更新してそれを行いました。

更新 2

若干の実装の相違があるようです。clang はこの問題を処理しているようです:

template <typename T> 
extern int variable;

template <> extern int variable<char>;
template <> extern int variable<int>;

#include <iostream>

int
main()
{
    std::cout << variable<char> << '\n';
    std::cout << variable<int> << '\n';
}

template <> int variable<char> = 23;
template <> int variable<int> = 24;

http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi

ただし、gcc でエラーが発生します。

prog.cc:4:13: error: explicit template specialization cannot have a storage class
 template <> extern int variable<char>;
             ^~~~~~

prog.cc:5:13: error: explicit template specialization cannot have a storage class
 template <> extern int variable<int>;
             ^~~~~~

標準と Core Issues リストを検索しましたが、どちらのコンパイラが正しいかを示すものは見つかりません。誰かがそのような証拠を見た場合は、この回答に喜んで含めます。

于 2016-01-24T17:55:59.320 に答える