c++ - Argument-dependent lookup within template -


i'm confused function-name lookup in context of template. know compiler delays argument-dependent identifier lookup in templated code until template instantiated. means can have syntax errors or call non-existent functions within templated code, , compiler won't complain unless instantiate template.

however, i've found discrepancy between different compilers, , i'm interested in knowing standard requires.

consider following code:

#include <iostream>  class foo {     public:      template <class t>     void bar(t v)     {         do_something(v);     } };  void do_something(std::string s) {     std::cout << "do_something(std::string)" << std::endl; }  void do_something(int x) {     std::cout << "do_something(int)" << std::endl; }  int main() {     foo f;     f.bar("abc");     f.bar(123); } 

note template member function foo::bar calls non-argument-dependent global function called do_something, hasn't been declared yet.

yet, gcc 4.6.3 happily compile above program. when run, output is:

do_something(std::string) do_something(int) 

here's ideone link.

so, looks though compiler delayed identifier lookup until after template instantiated, @ point able find do_something.

in contrast, gcc 4.7.2 not compile above program. produces following error:

test.cc: in instantiation of ‘void foo::bar(t) [with t = const char*]’: test.cc:27:13:   required here test.cc:10:3: error: ‘do_something’ not declared in scope, , no declarations found argument-dependent lookup @ point of instantiation [-fpermissive] test.cc:19:6: note: ‘void do_something(int)’ declared here, later in translation unit 

so, gcc 4.7.2 aware do_something later declared, refuses compile program because do_something not argument-dependent.

so, i'm assuming gcc 4.7.2 correct here, , gcc 4.6.3 incorrect. presumably, i'd need declare do_something before foo::bar defined. problem suppose want allow users of class foo extend behavior of foo::bar implementing own overloads of do_something. i'd need write like:

#include <iostream>  template <class t> void do_something(t v) {     std::cout << "do_something(t)" << std::endl; }  class foo {     public:      template <class t>     void bar(t v)     {         do_something(v);     } };  void do_something(int x) {     std::cout << "do_something(int)" << std::endl; }  int main() {     foo f;     f.bar("abc");     f.bar(123); } 

the problem here, overloads of do_something not visible within foo::bar, , never called. if call do_something(int), call do_something(t) rather overload int. thus, both gcc 4.6.3 , gcc 4.7.2, above program outputs:

do_something(t) do_something(t) 

so solutions here? how can allow users extend foo::bar implementing own overloads of do_something?

as far overloading do_something goes, need specialize original template:

template<> void do_something<int>(int x) {     std::cout << "do_something(int)" << std::endl; } 

edit : @matthieum. pointed out, function template specialization can yield weird results if need overload function (and @ point you'll need to, since function templates can't partially specialized). see matthieu's link herb sutter's article why not specialize function templates? full explanation.

what recommended instead use static function wrapped in struct, allows partial specialization , removes name resolution problem comes overloaded function templates.

template<typename t> struct dosomething {     static void do_something(t v) {         std::cout << "do_something(t)" << std::endl;     } };  struct foo {     template <class t>     void bar(t v) {         dosomething<t>::do_something(v);     } };  // can specialize safely template<> struct dosomething<int> {     static void do_something(int v) {         std::cout << "do_something(int)" << std::endl;     } }; 

Comments

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -