So I have some code here that compiles with gcc, clang, and msvc:
#include <cstdio>
#include <type_traits>
struct c_class;
template <class T> struct holder { friend auto adl_lookup(holder<T>); };
template <class C, class T> struct lookup {
friend auto adl_lookup(holder<T>) { return holder<C>{}; }
};
struct cpp_class : lookup<cpp_class, c_class *> {
cpp_class() {}
};
int main() {
static_assert(std::is_same<holder<cpp_class>,
decltype(adl_lookup(holder<c_class *>{}))>{},
"Failed");
}
The reason adl_lookup
is defined in the lookup
class instead of the holder
class is so that you can do a "reverse" lookup from c_class
to cpp_class
when you inherit from the CRTP class lookup<cpp_class, c_class *>
. So the friend function can't be moved to the holder
class.
However, on gcc I get a warning about non template friend function:
<source>:9:37: warning: friend declaration 'auto adl_lookup(holder<T>)' declares a non-template function [-Wnon-template-friend]
9 | friend auto adl_lookup(holder<T>);
| ^
<source>:9:37: note: (if this is not what you intended, make sure the function template has already been declared and add '<>' after the function name here)
If I try to fix this by forward declaring the function and then using <>
, it doesnt compile with gcc or msvc(although it does compile with clang):
#include <cstdio>
#include <type_traits>
struct c_class;
template <class T> struct holder;
template <class T> auto adl_lookup(const holder<T> &);
template <class T> struct holder {};
template <class C, class T> struct lookup {
friend auto adl_lookup<>(const holder<T> &) { return holder<C>{}; }
};
struct cpp_class : lookup<cpp_class, c_class *> {
cpp_class() {}
};
int main() {
static_assert(std::is_same<holder<cpp_class>,
decltype(adl_lookup(holder<c_class *>{}))>{},
"Failed");
}
Am I using standard-compliant C++ here(in both snippets)? Is there a reason to be concerned about gcc's warning about non-template friend or is it just a false positive that I can safely ignore?
adl_lookup
declared twice? – Kutenailookup
is instantiated. This is an unusual thing to want to do (hence the warning), but occasionally useful. – Alcestisholder
ADL wouldn't find it. – Quelpart