c++ - "ambiguous overload for 'operator<<'" *without* a catch-all overload -
so trying implement xorshift prngs parameterised stl-style class random
, e.g. std::mersenne_twister_engine
, can use quite convenient distributions random
library etc.
anyway, have problem overloading operator<<
and, frankly, completely stumped.
the class parameterised this:
template <size_t __n, int_least8_t __a, int_least8_t __b, int_least8_t __c, uint64_t __m> class xorshift_engine { ...
the overload declared friend
inside class this:
template <size_t __n_, int_least8_t __a_, int_least8_t __b_, int_least8_t __c_, uint64_t __m_, typename _chart, typename _traits> friend std::basic_istream<_chart, _traits>& operator<< (std::basic_ostream<_chart, _traits>& _os, const xorshift_engine<__n_, __a_, __b_, __c_, __m_>& _x);
and implementation outside class looks this:
template <size_t __n, int_least8_t __a, int_least8_t __b, int_least8_t __c, uint64_t __m, typename _chart, typename _traits> std::basic_ostream<_chart, _traits>& operator<< (std::basic_ostream<_chart, _traits>& _os, const xorshift_engine<__n, __a, __b, __c, __m>& _x) { ... }
when try compile following:
#include <iostream> #include <random> #include "xorshift.hpp" using namespace std; int main() { xorshift1024star bip(2345); mt19937_64 bip2(2345); cout << bip << endl; cout << endl << bip2 << endl; return 0; }
(xorshift1024star
instantiation of xorshift_engine
class:
typedef xorshift_engine<16, -31, 11, 30, 1181783497276652981ull> xorshift1024star;
) error (i replaced username in file paths ---
):
c:\users\---\documents\randgen.cpp: in function 'int main()': c:\users\---\documents\randgen.cpp:11:7: error: ambiguous overload 'operator<<' (operand types 'std::ostream {aka std::basic_ostream<char>}' , 'xorshift1024star {aka xorshift_engine<16ull, -31, 11, 30, 1181783497276652981ull>}') cout << bip << endl; ^ c:\users\---\documents\randgen.cpp:11:7: note: candidates are: in file included c:\users\---\documents\randgen.cpp:3:0: c:\users\---\documents\xorshift.hpp:898:1: note: std::basic_ostream<_chart, _traits>& operator<<(std::basic_ostream<_chart, _traits>&, const xorshift_engine<__n, __a, __b, __c, __m>&) [with long long unsigned int __n = 16ull; signed char __a = -31; signed char __b = 11; signed char __c = 30; long long unsigned int __m = 1181783497276652981ull; _chart = char; _traits = std::char_traits<char>] operator<< (std::basic_ostream<_chart, _traits>& _os, ^ c:\users\---\documents\xorshift.hpp:858:2: note: std::basic_istream<_chart, _traits>& operator<<(std::basic_ostream<_chart, _traits>&, const xorshift_engine<__n_, __a_, __b_, __c_, __m_>&) [with long long unsigned int __n_ = 16ull; signed char __a_ = -31; signed char __b_ = 11; signed char __c_ = 30; long long unsigned int __m_ = 1181783497276652981ull; _chart = char; _traits = std::char_traits<char>; long long unsigned int __n = 16ull; signed char __a = -31; signed char __b = 11; signed char __c = 30; long long unsigned int __m = 1181783497276652981ull] operator<< (std::basic_ostream<_chart, _traits>& os, ^ in file included c:/mingw-w64/x86_64-4.9.0-posix-seh-rt_v3-rev1/mingw64/x86_64-w64-mingw32/include/c++/iostream:39:0, c:\users\---\documents\randgen.cpp:1: c:/mingw-w64/x86_64-4.9.0-posix-seh-rt_v3-rev1/mingw64/x86_64-w64-mingw32/include/c++/ostream:602:5: note: std::basic_ostream<_chart, _traits>& std::operator<<(std::basic_ostream<_chart, _traits>&&, const _tp&) [with _chart = char; _traits = std::char_traits<char>; _tp = xorshift_engine<16ull, -31, 11, 30, 1181783497276652981ull>] <near match> operator<<(basic_ostream<_chart, _traits>&& __os, const _tp& __x) ^ c:/mingw-w64/x86_64-4.9.0-posix-seh-rt_v3-rev1/mingw64/x86_64-w64-mingw32/include/c++/ostream:602:5: note: no known conversion argument 1 'std::ostream {aka std::basic_ostream<char>}' 'std::basic_ostream<char>&&'
for reference, how overload declared inside mersenne_twister_engine
in bits/random.h
:
template<typename _uinttype1, size_t __w1, size_t __n1, size_t __m1, size_t __r1, _uinttype1 __a1, size_t __u1, _uinttype1 __d1, size_t __s1, _uinttype1 __b1, size_t __t1, _uinttype1 __c1, size_t __l1, _uinttype1 __f1, typename _chart, typename _traits> friend std::basic_ostream<_chart, _traits>& operator<<(std::basic_ostream<_chart, _traits>& __os, const std::mersenne_twister_engine<_uinttype1, __w1, __n1, __m1, __r1, __a1, __u1, __d1, __s1, __b1, __t1, __c1, __l1, __f1>& __x);
and implementation in bits/random.tcc
:
template<typename _uinttype, size_t __w, size_t __n, size_t __m, size_t __r, _uinttype __a, size_t __u, _uinttype __d, size_t __s, _uinttype __b, size_t __t, _uinttype __c, size_t __l, _uinttype __f, typename _chart, typename _traits> std::basic_ostream<_chart, _traits>& operator<<(std::basic_ostream<_chart, _traits>& __os, const mersenne_twister_engine<_uinttype, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __x) { ... }
if comment out cout << bip << endl;
line in test code, compiles , runs without error, overload fine, mine not.
i out of ideas. missing? more grateful if me.
edit: suggesting it's "template friends" problem should solve forward-declaring function, have added
template <size_t __n, int_least8_t __a, int_least8_t __b, int_least8_t __c, uint64_t __m> class xorshift_engine; template <size_t __n, int_least8_t __a, int_least8_t __b, int_least8_t __c, uint64_t __m, typename _chart, typename _traits> std::basic_ostream<_chart, _traits>& operator<< (std::basic_ostream<_chart, _traits>& _os, const xorshift_engine<__n, __a, __b, __c, __m>& _x);
before class body/implementation, , same error upon attempting compile.
edit2: simplified example giving same compile error:
//file "failclass.hpp" #ifndef _failclass_hpp #define _failclass_hpp #include <iosfwd> #include <type_traits> template <int n> class failclass { private: static constexpr int k = n; public: template<int n1, typename _chart, typename _traits> friend std::basic_istream<_chart, _traits>& operator<< (std::basic_ostream<_chart, _traits>& _os, const failclass<n1>& _x); }; template<int n1, typename _chart, typename _traits> std::basic_ostream<_chart, _traits>& operator<< (std::basic_ostream<_chart, _traits>& _os, const failclass<n1>& _x) { _os << _x.k; return _os; } #endif // _failclass_hpp
try compile this:
//file "failtest.cpp" #include <iostream> #include "failclass.hpp" using namespace std; int main() { failclass<5> a; cout << a; return 0; }
leaving rest of answer below value, particular error typo:
template <size_t __n_, int_least8_t __a_, int_least8_t __b_, int_least8_t __c_, uint64_t __m_, typename _chart, typename _traits> friend std::basic_istream<_chart, _traits>& // ^ -- meant std::ostream!!!!! operator<< (std::basic_ostream<_chart, _traits>& _os, const xorshift_engine<__n_, __a_, __b_, __c_, __m_>& _x);
the template defined @ namespace level , friend take same arguments, have different return type.
most of following not direct answer error message, tackles root problem got it. believe forward declaration should have fixed it. if doesn't, should provide scce.
for sake of discussion, lets simplify bit code template single argument want implement operator<<
. friend declaration:
template <typename t> class tmpl { friend std::ostream& operator<<(std::ostream&, tmpl const &); };
provides declaration non-template standalone function operator<<
taking std::ostream&
, tmpl<t> const &
. there important detail here, not befriending template, or any free function. given specialization tmpl<int>
, declaration befriends function in same namespace following signature:
std::ostream& operator<<(std::ostream& out, tmpl<int> const & obj) { // can access tmpl<int> internals! return out; }
while possible approach, don't want have manually provide different free function each specialization of template.
at point there interesting feature of friend
declaration: can provide definition inside class, friend declaration:
template <typename t> class tmpl { friend std::ostream& operator<<(std::ostream out, tmpl const & t) { // definition goes here return out; } };
the interesting point here that, each specialization of tmpl
, compiler generate non-template free function has access internals of type.
now, in particular case, might want consider other alternatives. first comes mind, use it, not make operator<<
friend, provide print
function (to can add other arguments control output), , implement operator<<
in terms of public interface calling print
. can opt still make operator<<
friend defined inside class [1], or can provide templated operator<<
calls print
:
template <typename t> class tmpl { public: std::ostream& print(std::ostream& out) const; // option 1: friend std::ostream& operator<<(std::ostream& out, tmpl const & obj) { return obj.print(out); } }; // option 2: template <typename t> std::ostream& operator<<(std::ostream& out, tmpl<t> const & obj) { return obj.print(out); }
a different alternative (which don't recommend, well, sake of completeness) declare template above friend:
template <typename t> class tmpl { public: template <typename u> friend std::ostream& operator<<(std::ostream& out, tmpl<u> const & obj); }; // template defined option 2 above
but bad idea (and alternative opted for), operator<< <int>
have access tmpl<double>
, , quite easy break encapsulation.
a better alternative befriend only specialization of above template matches arguments, bit more convoluted in code:
template <typename t> class tmpl; template <typename t> std::ostream& operator<<(std::ostream&, tmpl<t> const &); template <typename t> class tmpl { friend std::ostream& operator<< <t>(std::ostream&, tmpl<t> const &); };
1 possible reason still make operator<<
friend if implemented in terms of public interface hides operator normal lookup, , makes available adl.
Comments
Post a Comment