C ++テンプレートクラスを転送宣言するにはどうすればよいですか?


98

次のようなテンプレートクラスがあるとします。

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

誰かがこのクラスをヘッダーファイルで転送宣言するにはどうすればよいですか?

回答:


102

これはあなたがそれをする方法です:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

デフォルトはforward宣言にあり、実際の定義にはないことに注意してください。


定義にデフォルトがリストされているクラスを前方宣言することは可能です。私の答えを見てください。
Elliott

同意しません。この規格では、「テンプレートパラメータには、同じスコープ内の2つの異なる宣言によってデフォルトの引数を与えてはならない」とあります。そして、最初の宣言だけでデフォルトについて何も見つかりませんでした。また、定義にforward宣言とデフォルトが含まれるコードは、正常にコンパイルおよび実行されます。あなたが主張していることについて確信がありますか?標準からの引用を提供できますか?
olek stolar

@エリオットそれは本当のようです。標準[17.1.9]は次のように述べています:「デフォルトのテンプレート引数テンプレート宣言で指定されるかもしれません。」そうである必要はありませんが、そうかもしれません。したがって、他の回答が最初の宣言にあるべきであると主張する理由がわかりません。
olek stolar

そして、定義にデフォルトを含める方がはるかに便利です。
olek stolar

8

テンプレートのデフォルト引数は、テンプレートの最初の宣言に対してのみ宣言できます。ユーザーがクラステンプレートを宣言して転送できるようにする場合は、転送ヘッダーを指定する必要があります。デフォルトを使用して他の人のクラステンプレートを転送宣言したい場合は、運が悪いです。


定義にデフォルトがリストされているクラスを前方宣言することは可能です。私の答えを見てください。
Elliott

同意しません。この規格では、「テンプレートパラメータには、同じスコープ内の2つの異なる宣言によってデフォルトの引数を与えてはならない」とあります。そして、最初の宣言だけでデフォルトについて何も見つかりませんでした。また、定義にforward宣言とデフォルトが含まれるコードは、正常にコンパイルおよび実行されます。あなたが主張していることについて確信がありますか?標準からの引用を提供できますか?
olek stolar

3

定義がデフォルトの引数を示すテンプレートクラスを宣言できます、クラスを参照するときはいつでも、定義が導入されるまで、すべての引数を含める必要があります。

例えば。std::vector含めずに使用しましょう(2番目の引数はstd::vectorデフォルトで定義されています):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

次に、ベクターを含めずに使用できます。例:

int main()
{
    Foo(3);
}

そして、私たちはそれ std::vector例えばで使うことができます:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main()
{
    Foo(std::vector<int>(3));
}

私が上でこの作品の基準をチェックしますが、していないclang/はgccして-std=c++98まで-std=c++17それが正式に標準ではありませんので、もしそれがそう非公式になりそうです。


多分あなたは空の山括弧を忘れますFoo<> foo;
olek stolar

@ OleksijPlotnyc'kyjあなたは正しい。ありがとう。その追加を削除しました。
エリオット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.