https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83035

            Bug ID: 83035
           Summary: Using decltype fails with an operator using non-ADL
                    lookup
           Product: gcc
           Version: 7.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: tonvandenheuvel at gmail dot com
  Target Milestone: ---

Created attachment 42639
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42639&action=edit
preprocessed source file

The following code generates an incorrect compiler error using GCC 7.2.0:

#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 UnionAB = details::UnionResultType<N::A, N::B>;
  return 0;
}

(see: https://godbolt.org/g/2rfkh5)

'g++ -std=c++17 -save-temps main.cpp' reports:

main.cpp: In substitution of ‘template<class T, class U> using UnionResultType
= decltype ((declval<T>() | declval<U>())) [with T = N::A; U = N::B]’:
main.cpp:24:54:   required from here
main.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>());

The operator is in scope, so this should not be an issue. Writing instead:

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

does compile. See also:
https://stackoverflow.com/questions/47356994/using-decltype-with-an-operator-using-non-adl-lookup.

Reply via email to