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
Post a Comment