Using decltype with an operator using non-ADL lookup

Viewed 84

I have the following (contrived) code:

#include <utility>

namespace N
{
  struct A {};
  struct B {};
}

namespace operators
{
  bool operator|(N::A, N::B) { return true; };
}

namespace details
{
  using namespace operators;

  template<typename T, typename U>
  using UnionResultType = decltype(std::declval<T>() | std::declval<U>());
}

int main()
{
  {
    using namespace operators;
    using UnionAB = decltype(std::declval<N::A>() | std::declval<N::B>());
    static_assert(std::is_same<UnionAB, bool>::value);
  }

  {
    using UnionAB = details::UnionResultType<N::A, N::B>;
  }

  return 0;
}

GCC has a problem compiling the UnionAB declaration in the second block:

operators.cpp: In substitution of ‘template<class T, class U> using UnionResultType = decltype
((declval<T>() | declval<U>())) [with T = N::A; U = N::B]’:
operators.cpp:31:56:   required from here
operators.cpp:19:54: error: no match for ‘operator|’ (operand types are ‘N::A’ and ‘N::B’)
using UnionResultType = decltype(std::declval<T>() | std::declval<U>());

Even though there is a using namespace operators within the scope defining the templated UnionResultType, GCC fails to find the operator overload.

I am using GCC 7.2.0 (C++11, 14, and 17 mode all have the same problem).

Is there some issue in the code, or is this a compiler issue? In case this is a compiler issue, is this a known issue?

0 Answers
Related