テンプレート型の正しいコンストラクターを呼び出す方法は?


21

次のコードでは、コメント行をそのすぐ上の行と同じように機能させるにはどうすればよいですか?

テンプレートの適切なコンストラクターを呼び出す汎用コードにしたいと思いTypeます。

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }
};

int main()
{
    Class<std::string> a = std::string("abc");
    // Class<std::string> b = "abc";
    std::cout << a.data << std::endl;
    return 0;
}

回答:




13
Class<std::string> b = "abc";

あるコピーの初期化。2つのユーザー定義の変換が含まれるため、機能しません。

  • からconst char*までstd::string
  • からstd::stringまでClass<std::string>

ただし、許可されるのは1つだけです。

あなたが書くとき

Class<std::string> b("abc");
// or
Class<std::string> b{"abc"};

直接初期化を使用します。これで機能するのは、ユーザー定義の変換が1つだけ使用されるためです。

  • からconst char*までstd::string

0

を変更できる場合はClass、テンプレート化された変換コンストラクターを追加できます。次に、例に書かれているようにコメント行をコンパイルすることができます。ただし、見つけにくいバグが発生する可能性があるため、適切な理由なしに暗黙の変換を使用することは一般に推奨されません(C ++コアガイドラインを参照)。

#include <string>
#include <iostream>

template <typename Type>
struct Class
{
    Type data;
    Class(Type data) : data(data) { }

    template<typename Other>
    Class(Other other_data) : data(other_data) {}
};


int main()
{
    Class<std::string> a = std::string("abc");
    Class<std::string> b = "abc";
    Class<std::string> c = a;

    std::cout << b.data << std::endl;
    return 0;
}

C ++ 14を使用できる場合は、を使用してstd::literals::string_literals::operator""s、変換コンストラクターを削除できます。すると、あなたの行は次のようになります:

using namespace std::literals;

Class<std::string> b = "abc"s;

ここにライブコード。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.