c++ - Overload Resolution in a Namespace -
i attempting call overloaded function inside namespace , struggling bit.
working example 1: no namespace
class c {}; inline void overloaded(int) {} template<typename t> void try_it(t value) { overloaded(value); } inline void overloaded(c) {} int main() { try_it(1); c c; try_it(c); return 0; }
working example 2: overloads defined before template
class c {}; namespace n { inline void overloaded(int) {} inline void overloaded(c) {} } template<typename t> void try_it(t value) { n::overloaded(value); } int main() { try_it(1); c c; try_it(c); return 0; }
broken example 3: overloads after template
class c {}; namespace n { inline void overloaded(int) {} } template<typename t> void try_it(t value) { n::overloaded(value); } namespace n { inline void overloaded(c) {} } int main() { try_it(1); c c; try_it(c); // /tmp/test.cpp: in function ‘void try_it(t) [with t = c]’: // /tmp/test.cpp:19:15: instantiated here // /tmp/test.cpp:8:7: error: cannot convert ‘c’ ‘int’ argument ‘1’ ‘void n::overloaded(int)’ return 0; }
why case? need able declare or define overload after template function?
this problem of dependent name lookup.
in expression overloaded(value);
, name overloaded
dependent per [temp.dep]/1.
as far know, in expression n::overloaded(value)
, name overloaded
(in id-expression n::overloaded
) not dependent.
dependent name lookup peculiar, [temp.dep.res]/1
in resolving dependent names, names following sources considered:
- declarations visible @ point of definition of template.
- declarations namespaces associated types of function arguments both instantiation context , definition context.
(there's point of instantiation function templates @ end of file, declarations associated namespaces can found.)
for non-dependent names, normal lookup rules apply (lookup definition context).
therefore, find names declared after definition of template, have dependent and found via adl.
a simple workaround introduce parameter function overloaded
or wrap argument, such 1 of arguments of function has namespace n
associated:
#include <iostream> class c {}; namespace n { struct adl_helper {}; inline void overloaded(int, adl_helper = {}) { std::cout << "n::overloaded(int,..)" << std::endl; } } template<typename t> void try_it(t value) { overloaded(value, n::adl_helper{}); } namespace n { inline void overloaded(c, adl_helper = {}) { std::cout << "n::overloaded(c,..)" << std::endl; } } int main() { try_it(1); c c; try_it(c); }
alternatively:
namespace n { template < typename t > struct wrapper { t elem; }; inline void overloaded(wrapper<int>) { std::cout << "n::overloaded(wrapper<int>)" << std::endl; } } template<typename t> void try_it(t value) { overloaded(n::wrapper<t>{value}); } namespace n { inline void overloaded(wrapper<c>) { std::cout << "n::overloaded(wrapper<c>)" << std::endl; } }
Comments
Post a Comment