llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.39k stars 12.15k forks source link

SFINAE issue with constexpr operator #30111

Closed de9ccd5f-6521-4b39-ab30-f4e04ed39258 closed 8 years ago

de9ccd5f-6521-4b39-ab30-f4e04ed39258 commented 8 years ago
Bugzilla Link 30763
Resolution DUPLICATE
Resolved on Oct 21, 2016 14:37
Version 3.9
OS Linux
Attachments test code (also in the text)
CC @DougGregor,@zygoloid

Extended Description

The following code fails to compile:

include

include

template <typename TT1, typename TT2> struct Helper { template <typename T1, typename T2> static auto test(int) -> decltype(std::declval() == std::declval(), std::true_type());

template <typename T1, typename T2>
static auto test(...) -> std::false_type;

using Result = decltype(test<TT1, TT2>(0));

};

template <typename TT1, typename TT2> constexpr bool isEqualityComparable() { using Result = typename Helper<TT1, TT2>::Result; return Result::value; }

struct S { };

template struct Wrapper { T t; };

// Removing constexpr here will make the code compilable template <typename T1, typename T2> constexpr bool operator==(const Wrapper& w1, const Wrapper& w2) { return w1.t == w2.t; }

using W = Wrapper;

int main() { isEqualityComparable<W, W>(); }

The result is:

$ clang++-3.9 error_test.cpp -std=c++11 error_test.cpp:37:17: error: invalid operands to binary expression ('const S' and 'const S') return w1.t == w2.t;


error_test.cpp:8:58: note: in instantiation of function template specialization 'operator==<S, S>' requested here
    static auto test(int) -> decltype(std::declval<T1>() == std::declval<T2>(), std::true_type());
                                                         ^
error_test.cpp:13:29: note: while substituting explicitly-specified template arguments into function template 'test'
    using Result = decltype(test<TT1, TT2>(0));
                            ^
error_test.cpp:19:29: note: in instantiation of template class 'Helper<Wrapper<S>, Wrapper<S> >' requested here
    using Result = typename Helper<TT1, TT2>::Result;
                            ^
error_test.cpp:44:5: note: in instantiation of function template specialization 'isEqualityComparable<Wrapper<S>, Wrapper<S> >' requested here
    isEqualityComparable<W, W>();
    ^
error_test.cpp:35:16: note: candidate template ignored: could not match 'Wrapper<type-parameter-0-0>' against 'const S'
constexpr bool operator==(const Wrapper<T1>& w1, const Wrapper<T2>& w2)

Also:
1) -std=c++14 gives the same result,
2) removing constexpr from operator== fixes the problem,
3) GCC 4.9.3 produces a similar error while GCC 5.2.0 compiles it without errors.
ec04fc15-fa35-46f2-80e1-5d271f2ef708 commented 8 years ago

This bug has been marked as a duplicate of bug llvm/llvm-project#23509