14

g++ (バージョン 4.8.1_1、Macports) および clang++ (バージョン 3.3、Macports) 用の TMP を多用するコードを作成しています。g++ は次のコード リストをUNBRIDLED FURYで拒否しますが、clang++ はそれを優雅見事にコンパイルします。

  • 正しいのはどのコンパイラですか? (私はそれが g++ であると強く疑っていますが、バグ レポートを提出する前に他の人から安心を得たいと思っています。)
  • 提案する簡単またはエレガントな回避策はありますか? (テンプレート エイリアスを使用する必要があるため、g++ にコードを受け入れさせる構造体に切り替えることはオプションではありません。)

これがあなたのために作られたコードリストです。

template <class... Ts>
struct sequence;

template <int T>
struct integer;

// This definition of `extents` causes g++ to issue a compile-time error.
template <int... Ts>
using extents = sequence<integer<Ts>...>;

// However, this definition works without any problems.
// template <int... Ts>
// struct extents;

template <int A, int B, class Current>
struct foo;

template <int A, int B, int... Ts>
struct foo<A, B, extents<Ts...>>
{
    using type = int;
};

template <int B, int... Ts>
struct foo<B, B, extents<Ts...>>
{
    using type = int;
};

int main()
{
    using t = foo<1, 1, extents<>>::type;
    return 0;
}

g++ の出力は次のとおりです。

er.cpp: In function 'int main()':
er.cpp:39:41: error: ambiguous class template instantiation for 'struct foo<1, 1, sequence<> >'
  using t = typename foo<1, 1, extents<>>::type;
                                         ^
er.cpp:26:8: error: candidates are: struct foo<A, B, sequence<integer<Ts>...> >
 struct foo<A, B, extents<Ts...>>
        ^
er.cpp:32:8: error:                 struct foo<B, B, sequence<integer<Ts>...> >
 struct foo<B, B, extents<Ts...>>
        ^
er.cpp:39:43: error: 'type' in 'struct foo<1, 1, sequence<> >' does not name a type
  using t = typename foo<1, 1, extents<>>::type;
                                           ^

これがclang ++の出力です:

ご協力いただきありがとうございます!

4

3 に答える 3

0

g++ が正しいと思います。この線

using t = foo<1, 1, extents<>>::type

推定されていないコンテキストでテンプレート パラメーターを使用しているため、テンプレート パラメーターに指定された実際の値を使用してあいまいさを解決することはできず、それらの型だけを使用するだけでは十分ではありません。

C++ 標準のセクション 14.8.2.5、パラ 4 には次のように記載されています。

ほとんどの場合、P を構成するために使用される型、テンプレート、および型以外の値は、テンプレート引数推定に参加します。つまり、それらはテンプレート引数の値を決定するために使用される場合があり、そのように決定された値は、他の場所で決定された値と一致する必要があります。ただし、特定のコンテキストでは、値は型推定に参加せず、代わりに別の場所で推定された、または明示的に指定されたテンプレート引数の値を使用します。テンプレート パラメーターが推定されないコンテキストでのみ使用され、明示的に指定されていない場合、テンプレート引数の推定は失敗します。

非推定コンテキストは次のとおりです。

x 修飾 ID を使用して指定されたタイプのネストされた名前指定子

...

セクション 14.8.2.4 パラ 11 は次のように述べています。

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

つまり、すべてのテンプレート引数に値が必要です。したがって、extents<> が型を特定できない場合、結果は標準に従ってあいまいになります。もっともらしい?

于 2013-07-17T19:32:57.450 に答える