8

私は次のコードを持っています(大きなコードチャンクで申し訳ありませんが、これ以上絞り込むことはできませんでした)

template <bool B>
struct enable_if_c {
      typedef void type;
};

template <>
struct enable_if_c<false> {};

template <class Cond>
struct enable_if : public enable_if_c<Cond::value> {};

template <typename X>
struct Base { enum { value = 1 }; };

template <typename X, typename Y=Base<X>, typename Z=void>
struct Foo;

template <typename X>
struct Foo<X, Base<X>, void> { enum { value = 0 }; };

template <typename X, typename Y>
struct Foo<X, Y, typename enable_if<Y>::type > { enum { value = 1 }; };

int main(int, char**) {
        Foo<int> foo;
}

しかし、gcc (v4.3) でのコンパイルに失敗します。

foo.cc: In function ‘int main(int, char**)’:
foo.cc:33: error: ambiguous class template instantiation for ‘struct Foo<int, Base<int>, void>’
foo.cc:24: error: candidates are: struct Foo<X, Base<X>, void>
foo.cc:27: error:                 struct Foo<X, Y, typename enable_if<Y>::type>
foo.cc:33: error: aggregate ‘Foo<int, Base<int>, void> foo’ has incomplete type and cannot be defined

OK、あいまいです。しかし、特殊化を使用する場合、ほとんどの場合あいまいになるため、それが問題になるとは思っていませんでした。ただし、このエラーはクラスをenable_if<...>で使用した場合にのみトリガーされます。次のようなクラスに置き換えれば問題ありません。

template <typename X, typename Y>
struct Foo<X, Y, void > { enum { value = 2 }; };

このクラスはあいまいさを引き起こさないのに、他のクラスはなぜあいまいさを引き起こさないのですか? 真の::値を持つクラスの場合、2つは同じことではありませんか? とにかく、私が間違っていることについてのヒントは大歓迎です。

答えてくれてありがとう、私の本当の問題(コンパイラに最初の専門分野を選択させるため)は、私が望むように動作するように見えるものを置き換えるstruct Foo<X, Base<X>, void>ことで解決されましstruct Foo<X, Base<X>, typename enable_if< Base<X> >::type >た。

4

3 に答える 3

12

あなたの質問の要点はあなたが持っているということです:

template <typename X, typename Y, typename Z>
struct Foo {};

template <typename X>
struct Foo<X, Base<X>, void> {};                   // #1

template <typename X, typename Y>
struct Foo<X, Y, typename whatever<Y>::type> {};   // #2

そしてあなたはそれをに合わせようとしています

Foo<int, Base<int>, void>

明らかに、両方の専門分野が一致します(最初は、、X = int2番目はX = int, Y = Base<int>)。

標準のセクション14.5.4によると、一致する特殊化がさらにある場合は、それらの間で半順序(14.5.5.2で定義)が構築され、最も特殊化されたものが使用されます。ただし、あなたの場合、どちらももう一方よりも専門的ではありません。(簡単に言えば、後者のテンプレートの各タイプパラメータをあるタイプに置き換えて、結果として前者の署名を取得できる場合、テンプレートは別のテンプレートよりも特殊化されます。また、持っていてwhatever<Y>::type置き換える場合は、そうではありません。処理は行われません。)YBase<X>whatever<Base<X> >::typevoid

#2に置き換える場合

template <typename X, typename Y>
struct Foo<X, Y, void > {};                        // #3

次に、候補セットには両方のテンプレートが含まれますが、#1は#3よりも特殊化されているため、選択されます。

于 2009-07-22T19:31:16.287 に答える
-1

欠けていませんか

<

シンボル?

于 2009-07-22T17:20:36.067 に答える
-2

「<」が欠落していると思います。テンプレートは次のようになります。

template< typename T >
struct myStruct
{};

//OR

template< class T >
struct myStruct
{};
于 2009-07-22T17:22:54.563 に答える