c++ - Template functions in namespace cause errors -


assume following code:

#include <iostream>  template<typename t> struct link {     link(t&& val) : val(std::forward<t>(val)) {}      t val; };  template<typename t> std::ostream& operator<<(std::ostream& out, const link<t>& link) {     out << "link(" << link.val << ")";     return out; }  template<typename t> auto makelink(t&& val) -> link<t> {     return {std::forward<t>(val)}; }  namespace utils { template<typename any> constexpr auto removelinks(const any& any) -> const any& {     return any; }  template<typename t> constexpr auto removelinks(const link<t>& link) -> decltype(removelinks(link.val)) {     return removelinks(link.val); }  } /* utils */  int main() {     int k = 10;      auto link = makelink(makelink(k));      std::cout << link << std::endl;     std::cout << utils::removelinks(link) << std::endl; } 

for reason can't understand, generates following compilation errors g++-4.8:

/home/allan/codes/expr.cpp: in instantiation of ‘constexpr decltype (utils::removelinks(link.val)) utils::removelinks(const link<t>&) [with t = int&; decltype (utils::removelinks(link.val)) = const int&]’: /home/allan/codes/expr.cpp:88:32:   required ‘constexpr decltype (utils::removelinks(link.val)) utils::removelinks(const link<t>&) [with t = link<int&>; decltype (utils::removelinks(link.val)) = const int&]’ /home/allan/codes/expr.cpp:100:41:   required here /home/allan/codes/expr.cpp:88:32: error: invalid initialization of reference of type ‘const link<int&>&’ expression of type ‘const int’      return removelinks(link.val);                                 ^ /home/allan/codes/expr.cpp:89:1: error: body of constexpr function ‘constexpr decltype (utils::removelinks(link.val)) utils::removelinks(const link<t>&) [with t = int&; decltype (utils::removelinks(link.val)) = const link<int&>&]’ not return-statement  }  ^ /home/allan/codes/expr.cpp: in function ‘constexpr decltype (utils::removelinks(link.val)) utils::removelinks(const link<t>&) [with t = int&; decltype (utils::removelinks(link.val)) = const int&]’: /home/allan/codes/expr.cpp:89:1: warning: control reaches end of non-void function [-wreturn-type]  }  ^ 

while clang 3.3 gives:

test.cc:34:12: error: reference type 'const link<int &>' not bind lvalue of type 'const int' return removelinks(link.val);        ^~~~~~~~~~~~~~~~~~~~~ test.cc:46:25: note: in instantiation of function template specialization 'utils::removelinks<link<int &> >' requested here std::cout << utils::removelinks(link) << std::endl; 

if, however, namespace utils removed, compiles without errors (both gcc , clang), , execution outputs:

link(link(10)) 10 

why defining template functions (removelinks) in namespace causes such errors?

this problem result of issue point of declaration (1) combined dependent name lookup (2).

(1) in declaration

template<typename t> constexpr auto removelinks(const link<t>& link) -> decltype(removelinks(link.val)) 

the name removelinks, or more precisely, overload of removelinks, visible after complete declarator according [basic.scope.pdecl]/1. trailing-return-type part of declarator per [dcl.decl]/4. see this answer.

(2) in expression removelinks(link.val), name removelinks dependent per [temp.dep]/1, link.val dependent.

if how dependent names resolved, find [temp.dep.res]:

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.

the first bullet doesn't find second overload of removelinks because of point of declaration (1). second 1 doesn't find overload because namespace util not associated argument. why putting in global namespace or in namespace util works expected (live example).

for same reason, using qualified-id in trailing-return-type (like -> decltype(util::removelinks(link.val)) doesn't here.


Comments

Popular posts from this blog

wordpress - (T_ENDFOREACH) php error -

Export Excel workseet into txt file using vba - (text and numbers with formulas) -

Using django-mptt to get only the categories that have items -