By R. Martinho Fernandes


2012-04-30 00:18:09 8 Comments

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 comments

@R. Martinho Fernandes 2012-04-30 02:24:11

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.

@Johannes Schaub - litb 2012-04-30 18:44:48

could you please comment on the PR and add your testcase? your testcase is more critical imho, because it occurs during argument deduction (my testcase misses a substitution only at the end after argument deduction) and because clang differs from gcc.

Related Questions

Sponsored Content

1 Answered Questions

1 Answered Questions

2 Answered Questions

[SOLVED] Empty Pack Variadic Template

3 Answered Questions

[SOLVED] Why do my SFINAE expressions no longer work with GCC 8.2?

2 Answered Questions

2 Answered Questions

2 Answered Questions

1 Answered Questions

[SOLVED] clang vs gcc - empty generic lambda variadic argument pack

1 Answered Questions

[SOLVED] Are multiple non-type template parameter packs allowed?

Sponsored Content