12

他のクラスからコンストラクターを継承する必要があるクラスを作成しようとしていますが、それらのクラス自体から継承する必要はありません。

クラスの初期化中のある時点で、完全転送を使用して、コンストラクターが指定された引数と一致する型のオブジェクトを作成したいと考えています。

引数のないデフォルトのコンストラクターを除いて、あいまいさはありません。

これは私のコードです:

#include <string>

using namespace std;

//NOTE: this class is just an example to demonstrate the problem
class String {
    public:
        //default constructor to prevent ambiguity
        String() {}

        //construct from wstring
        template<typename... Args>
        String(enable_if<is_constructible<wstring, Args...>::value, Args>::type&&... args) : ws(forward<Args>(args)...) {}

        //construct from string
        template<typename... Args>
        String(enable_if<is_constructible<string, Args...>::value, Args>::type&&... args) : s(forward<Args>(args)...) {}
    private:
        string s;
        wstring ws;
};

void foo(const String& string) {
}

int main()
{
    foo(L"123");
    foo("123");
    return 0;
}

私は多くのことを試しましたが、うまくいきません。

  • 現在のアプローチenable_ifでは、テンプレート引数を自動的に差し引くことができません(私は思う)
  • コンストラクターを使用enable_ifしているため、戻り値には使用できません
  • コンストラクターが可変長であるため、別のデフォルトパラメーターを追加しても機能しenable_ifません
  • 関数の引数から削除するとenable_if、コンパイラは無効なオーバーロードについて不平を言います(もちろん)

この問題を解決するエレガントな方法はありますか?

編集: 標準で許可されている1つの暗黙的な変換は、私のクラスでは発生しないはずです。[コード例を編集]

上記の例で機能する 1 つの解決策は、単一の可変引数コンストラクターを定義し、引数を条件付き初期化関数に完全転送することです。ただし、メンバーはデフォルトで構築される必要があり、これは他の場合には機能しない可能性があるため、このオーバーヘッドを回避したいと思います。

(物事をより明確にすることができる場合は、自由に質問を編集してください)

4

1 に答える 1

2

問題と解決策がわかりません。メソッドまたはコンストラクターに 2 つの異なる型を使用する場合は、単純に両方の型を記述できます。そのため、SFINAE でテンプレートを用意する必要はありません。これは専門化によって簡単に行うことができます。

class A 
{
    public:
    template <typename ... Args>
    A(const wstring &, Args ... );

    template <typename ... Args>
    A(const string &, Args ...);
};

1つのタイプのみに完全に一致するテンプレートを持つことは、実際には意味的にテンプレートではありません:-)

あなたのコメントを読んだ後、私はこの解決策を得ました:

class foo
{
    public:
        template <typename ... Args>
        foo( const string &&x, Args ... ) { cout << "Using string" << endl; }

        template <typename ... Args>
        foo( const wstring &&x, Args ...) { cout << "Using wstring" << endl; }
};

int main()
{
    foo("123");
    foo(L"123");

    foo("123", 1);
    foo(L"123", 1.11);
    return 0;
}

そして、これは期待どおりに戻ります:

Using string
Using wstring
Using string
Using wstring
于 2013-10-20T12:44:10.213 に答える