如果包是空的,是否在可变参数包类型上执行替换?

时间:2012-04-30 00:18:10

标签: c++ c++11 g++ clang sfinae

考虑以下计划:

#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 glady接受此计划。我最近的clang 3.1 build声称对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 个答案:

答案 0 :(得分:11)

我相信我找到了相关的标准。 §14.8.2p7说:

  

替换发生在函数类型和模板参数声明中使用的所有类型和表达式中。

由于模板参数声明中使用了EnableIf<dependent_true_type<T>>,因此应进行替换,这是a bug in clang