45

次のクラス テンプレート 'X' とその部分的な特殊化について考えてみましょう。

template <class ...Types>
struct X {};               // #1

template <class T1>
struct X<T1> {};           // #2

template <class T1, class ...Types>
struct X<T1, Types...> {}; // #3

X<int> x;                  // #2 or #3 ?

X<int> があいまいであると思われます。なぜなら:

#2 と #3 の両方が #1 よりも特化されていることは明らかであり、#2 と #3 が比較されます。14.5.5.2 に従って、次の #2' と #3' のどちらが専門的かを考えてみましょう。

template <class T1>
void f(X<T1>);             // #2'

template <class T1, class ...Types>
void f(X<T1, Types...>);   // #3'

14.8.2.4 によると、最初のステップは #2' を引数テンプレートとして、 #3' をパラメーター テンプレートとして使用するテンプレート引数推定です。引数の型が X<A1> のみの場合、推定される T1 は A1 で、Types は空です。

A = X<A1>, P = X<T1, Types...>  =>  T1 = A1, Types = {}

2 番目のステップは、#3' を引数テンプレートとして、#2' をパラメーター テンプレートとして使用して実行されます。引数の型が X<A1, Args...> のみの場合、14.8.2.5/9 (この段落は最近 N3281 によって改訂されたことに注意してください) によると、Args は単純に無視され、推定された T1 は A1 であり、引数の推定は成功します。

A = X<A1, Args...>, P = X<T1>  =>  T1 = A1 (Args is ignored)

最後に、双方向の引数推定が成功しました。したがって、#2 は #3 と同じように専門化されています。結論として、 X<int> はあいまいです。

私の質問は、「私の解釈は正しいですか?」

この解釈が正しければ、20.9.7.6/3 の「std::common_type」の定義は不適切です。

template <class ...T>
struct common_type;            // #1

template <class T>
struct common_type<T>          // #2
{
    typedef T type;
};

template <class T, class U>
struct common_type<T, U>       // #3
{
    typedef
        decltype(true ? declval<T>() : declval<U>())
    type;
};

template <class T, class U, class ...V>
struct common_type<T, U, V...> // #4
{
    typedef typename
        common_type<typename common_type<T, U>::type, V...>::type
    type;
};

common_type<A, B> を使用すると、#3 と #4 が曖昧になります。

注: 最初の例では、GCC 4.7.0 (スナップショット) と Clang 3.0 は #2 を選択します。ただし、これらのコンパイラは信頼性が低いため、N3281 による他の変更には従いません。

4

1 に答える 1

8

14.8.2.4、セクション 11 (ドラフト N3242 を参照)。

ほとんどの場合、演繹が成功するためには、すべてのテンプレート パラメーターに値が必要ですが、部分的な順序付けのために、テンプレート パラメーターは、部分的な順序付けに使用されている型で使用されていなければ、値を持たないままにすることができます。[ 注: 非推定コンテキストで使用されるテンプレート パラメータは、使用されていると見なされます。—終わりのメモ] [例:

template <class T> T f(int); // #1
template <class T, class U> T f(U); // #2
void g() {
f<int>(1); // calls #1
}

あなたの場合、#3が使用されます。

于 2011-12-20T14:11:34.050 に答える