10

次のプログラムを検討してください。

#include <type_traits>

enum class dummy {};
template <typename T>
using EnableIf = typename std::enable_if<T::value, dummy>::type;
template <typename T>
using DisableIf = typename std::enable_if<!T::value, dummy>::type;

template <typename T>
struct dependent_true_type : std::true_type {};

template <typename T,
          EnableIf<dependent_true_type<T>>...>
std::true_type f();
template <typename T,
          DisableIf<dependent_true_type<T>>...>
std::false_type f();

static_assert(decltype(f<int>())::value, "");

int main() {}

GCC 4.7 はこのプログラムを喜んで受け入れます。私の最近のclang 3.1ビルドは、への呼び出しfがあいまいであると主張しています。

test.c++:22:24: fatal error: call to 'f' is ambiguous
static_assert(decltype(f<int>())::value, "");
                       ^~~~~~
test.c++:17:16: note: candidate function [with T = int, $1 = <>]
std::true_type f();
               ^
test.c++:20:17: note: candidate function [with T = int, $1 = <>]
std::false_type f();
                ^
1 error generated.

私が書いた場合、それはプログラムを受け入れますf<int, dummy{}>()

パックが空の場合、clang はパラメータ パックのタイプを考慮していないようで、候補セットから削除されません。GCC は、パックが空であってもパラメーター パック タイプの置換を実行するようであり、この置換は 1 つのオーバーロードで失敗するため、あいまいさはありません。

どちらが正しいですか?

4

1 に答える 1

11

関連する規格を見つけたと思います。§14.8.2p7 は次のように述べています。

置換は、関数の型とテンプレート パラメーターの宣言で使用されるすべての型と式で発生します。

EnableIf<dependent_true_type<T>>はテンプレート パラメータ宣言で使用されるため、置換が発生する必要があり、これはclangのバグです。

于 2012-04-30T02:24:11.240 に答える