1

クラス テンプレートの ctor オーバーロードの解決に単純な問題があります。

#include <iostream>
#include <string>

using namespace std;
enum EnumTypeVal { READ, WRITE };

template <class T>
class TemplateClassTest {
public:
    TemplateClassTest(const string & stringVal, T typeVal, EnumTypeVal e = READ,
                      const string & defaultStringVal = "default");
    TemplateClassTest(const string & stringVal, const char * charVal);
    TemplateClassTest(const string & stringVal, EnumTypeVal e = READ,
                      const string & defaultStringVal = "default");
private:
T type;
};

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, T typeVal,
                                        EnumTypeVal e,
                                        const string & defaultStringVal)
{
    type = typeVal;
    cout << "In TemplateClassTest(const string &, T, EnumTypeVal, "
            "const string &)" << endl;
}

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal,
                                        const char * charVal)
{
    cout << "In TemplateClassTest(const string &, const char *)" << endl;
}

template <class T>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, EnumTypeVal e,
                                        const string & defaultStringVal)
{
    cout << "In TemplateClassTest(const string &, EnumTypeVal, const string &)"
         << endl;
}

typedef TemplateClassTest<long long unsigned int> u32Type;
typedef TemplateClassTest<bool> boolType;

int main()
{
    u32Type l("test", "0"); //matches ctor 2
    u32Type v("test", 0); // ambiguity between ctor 1 and 2
    boolType b("test", "true"); //matches ctor 2
    return 0;
}

2 番目の呼び出しは、エラーをスローしてコンパイルに失敗します。

オーバーロードされた 'TemplateClassTest(const char [5], int) の呼び出しがあいまいです。

intがに一致するのはなぜconst char *ですか? この状況は、ctor 2 のconst char *toconst string &を変更することで解決できます。しかし、そうすると、boolType b("test", "true")ctor 2 ではなく ctor 1 に一致するようになりました。

私の要件は次のとおりです。

  • u32Type v("test", 0)ctor 1 と一致する必要があります
  • boolType b("test", "true")ctor 2 と一致する必要があります。

制限事項は次のとおりです。

  • ctor 1 および 3 の署名は変更できません
  • main() 内のユーザー コード呼び出しは変更できません。

どんな助けでも大歓迎です..ありがとう!

4

1 に答える 1

1

0は null ポインター定数であるため、あいまいです。ヌル ポインター定数は、任意のポインター型に暗黙的に変換できます ->ヌル ポインター変換。したがって、ctor 2 は実行可能です: TemplateClassTest(const string&, const char*).

整数リテラルとして、0タイプはintです。TemplateClassTest(const string&, T, EnumTypeVal = READ, const string & = "default")したがって、コンストラクター 1 は、 からintへの変換unsigned long long->整数変換を必要とします。

これら 2 つの変換、null ポインター変換整数変換は同じランク (変換) であるため、曖昧です。


[コンバージョンptr]/1

null ポインター定数は、整数型の整数定数式 prvalue であり、ゼロまたは type の prvalue に評価されますstd::nullptr_t。null ポインター定数はポインター型に変換できます。結果はその型のnull ポインター値であり、オブジェクト ポインターまたは関数ポインター型の他のすべての値と区別できます。このような変換は、ヌル ポインタ変換と呼ばれます。


可能ですが、制約に一致する醜い修正は、2番目のコンストラクターを次のように変更することです。

template<class U,
         class V = typename std::enable_if<std::is_same<U, const char*>{}>::type>
TemplateClassTest(const string & stringVal, U charVal);

つまり、貪欲なコンストラクター テンプレートであり、SFINAE によってconst char*2 番目の引数としてのみ受け入れるように制限されています。これにより、この ctor を一致させようとするときに 2 番目の引数に適用される暗黙の変換が大幅に制限されます。

アウトオブラインの定義は次のようになります。

template <class T>
template<class U, class V>
TemplateClassTest<T>::TemplateClassTest(const string & stringVal, U charVal)
{
    cout << "In TemplateClassTest(const string &, const char *)" << endl;
}
于 2013-11-05T18:52:39.113 に答える