Is substitution performed on a variadic parameter

2020-01-29 10:24发布

Consider the following program:

#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 accepts this program. My recent clang 3.1 build claims the call to f is ambiguous.

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.

It does accept the program if I write f<int, dummy{}>().

It seems clang does not consider the type of the parameter pack when the pack is empty, which leads to not removing it from the candidate set. GCC seems to perform substitution on the parameter pack type even if the pack is empty, and since said substitution fails for one overload, there is no ambiguity.

Which of the two is correct?

1条回答
放我归山
2楼-- · 2020-01-29 10:41

I believe I have found the relevant piece of standardese. §14.8.2p7 says:

The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations.

Since EnableIf<dependent_true_type<T>> is used in a template parameter declaration, substitution should occur and this is a bug in clang.

查看更多
登录 后发表回答