c++ - explicit specialization for overloading operator '<<' (left shift) -


lets have class, want overload operator based on enum type:

#include <iostream>  enum class option : char { normal, do_something_stupid };  class foo { public:      int i;         explicit foo(int a=0) : i(a) {};     /* overload operator '+=' based on 'option' */     template<option e = option::normal>     void operator+=(const foo& f) { += f.i; } };  /* explicit specialization operator += */ template<> void foo::operator+=<option::do_something_stupid>(const foo& f) { += (f.i +1000); }  int main() {     foo f1(1), f2(2);     f1 += f2;     std::cout << "\nf1 = " << f1.i;     f1.operator+=<option::do_something_stupid>(f2);     std::cout << "\nf1 = " << f1.i;      std::cout << "\n";     return 0; } 

this builds clean (ignoring fact pretty dump) both on g++ , clang++.

what if want overload '<<' operator same way? similar approach not seem work:

#include <ostream> #include <iostream>  enum class option : char { normal, do_something_stupid };  class foo { public:      int i;      explicit foo(int a=0) : i(a) {};      template<option e = option::normal>     friend std::ostream& operator<<(std::ostream& o, const foo& f)     { o << f.i; return o; } };  template<> std::ostream& operator<< <option::do_something_stupid>(std::ostream& o, const foo& f) {      o << f.i + 1000;     return o; }  int main() {     foo f1(1), f2(2);      std::cout << "\nf1= " << f1;     std::cout << "\nf2= ";     /* triggers error g++ */     std::cout.operator<< <option::do_something_stupid>(f1);      std::cout << "\n";     return 0; } 

according g++, call main operator invalid:

error: no match ‘operator<’ (operand types ‘<unresolved overloaded function type>’ , ‘option’) std::cout.operator<< <option::do_something_stupid>(f1); 

clang++ on other hand, produces different error message:

lsfov.cc:20:1: error: 'operator<<' cannot name of variable or data member operator<< <option::do_something_stupid>(std::ostream& o, const foo& f) ^ lsfov.cc:20:11: error: expected ';' @ end of declaration operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)           ^           ; lsfov.cc:20:12: error: expected unqualified-id operator<< <option::do_something_stupid>(std::ostream& o, const foo& f)            ^ lsfov.cc:33:15: error: reference non-static member function must called     std::cout.operator<< <option::do_something_stupid>(f1);     ~~~~~~~~~~^~~~~~~~~~ 

which goes on listing possible overload of '<<' standard library (if understand correctly), like:

/usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:108:7: note: possible target call       operator<<(__ostream_type& (*__pf)(__ostream_type&))       ^ /usr/bin/../lib/gcc/x86_64-redhat-linux/5.3.1/../../../../include/c++/5.3.1/ostream:117:7: note: possible target call       operator<<(__ios_type& (*__pf)(__ios_type&))       ^ 

what going on? kind of operator specialization possible/allowed? if so, proper way call operator? or clang correct , definition ill formed?

i think clang doesn't declaration of friend in relation specialisation. re-ordering them trick.

enum class option : char { normal, do_something_stupid };  // forward declare class , operator class foo;  template<option e = option::normal> std::ostream& operator<<(std::ostream& o, const foo& f);  // class declared friend operator class foo { private:     int i; public:     explicit foo(int a=0) : i(a) {};     template<option e>     friend std::ostream& operator<<(std::ostream& o, const foo& f); };  // operator implementations template<option e> std::ostream& operator<<(std::ostream& o, const foo& f) { o << f.i; return o; }  template<> std::ostream& operator<< <option::do_something_stupid>(std::ostream& o, const foo& f) {      o << f.i + 1000;     return o; } 

in addition, operator<< used in main not member cout, rather global.

int main() {     foo f1(1), f2(2);      std::cout << "\nf1= " << f1;     std::cout << "\nf2= ";     /* triggers error g++ */     operator<< <option::do_something_stupid>(std::cout, f1);      std::cout << "\n";     return 0; } 

sample here. g++ happy code above.


a note on operators in non-deduced context. assume using code here in greater project of sort, if operator being used non-deduced parameters, easier , clearer implement functionality in member method or free function (using friend required).


Comments

Popular posts from this blog

Hatching array of circles in AutoCAD using c# -

ios - UITEXTFIELD InputView Uipicker not working in swift -

Python Pig Latin Translator -