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.