c++ - User-defined overloaded operator * with std::chrono::duration -
i've created frequency class template intended work in conjunction std::chrono::duration. frequency object stores number of cycles per unit duration (both using template parameters types). idea multiplying frequency duration produces object of type rep. here's class definition. i've omitted relevant members.
#include <ratio> #include <chrono> using namespace std::chrono; template <typename rep, typename period = std::ratio<1>> class frequency { public: explicit frequency(rep cycles) : _cycles{cycles} { } friend rep operator *(const frequency<rep, period>& f, const duration<rep, period> d) { return f._cycles * d.count(); } friend rep operator *(const duration<rep, period> d, const frequency<rep, period>& f) { return f._cycles * d.count(); } private: rep _cycles; ///> number of cycles per period. };
the problem (i think) std::chrono::duration overloads * operator, follows:
template< class rep1, class period, class rep2 > duration<typename std::common_type<rep1,rep2>::type, period> constexpr operator*( const duration<rep1,period>& d, const rep2& s ); template< class rep1, class rep2, class period > duration<typename std::common_type<rep1,rep2>::type, period> constexpr operator*( const rep1& s, const duration<rep2,period>& d );
according cppreference, each of these methods
converts duration d 1 rep common type between rep1 , rep2, , multiplies number of ticks after conversion s.
i believe compiler trying use these overloaded operator templates instead of overloads. when write following code:
frequency<double> f{60.0}; duration<double> d{1.0}; double foo = f * d;
i following error in vs2013:
c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(1446) : error c2446: ':' : no conversion 'double' 'frequency<double,std::ratio<0x01,0x01>>' constructor class 'frequency<double,std::ratio<0x01,0x01>>' declared 'explicit' source_file.cpp(27) : see reference class template instantiation 'std::common_type<frequency<double,std::ratio<0x01,0x01>>,rep>' being compiled [ rep=double ]
and line 1446 vs implementation of std::common_type
.
so, there way ensure overloads called instead of in std::chrono::duration? know solve problem not using operator overloading , writing differently named method instead, i'd better understanding of what's going on here if possible. (plus overloads more convenient.)
also, apologize if question duplicate, unable find similar after searching.
in code:
frequency<double> f{60.0}; duration<double> d{1.0}; double foo = f * d;
the compiler says "oh, have find operator*
takes frequency<double>
, std::chrono::duration<double>
. operator*
possibilities there? , generates list of possibilities, composed of these two:
friend rep operator *(const frequency<rep, period>& f, const duration<rep, period> d) { return f._cycles * d.count(); } template< class rep1, class rep2, class period > duration<typename std::common_type<rep1,rep2>::type, period> constexpr operator*( const rep1& s, const duration<rep2,period>& d );
then, tries figure out exactly each of signatures are. first 1 is:
rep operator *(const frequency<rep, period>& f, const duration<rep, period> d)
and trying second 1 results in:
error c2446: ':' : no conversion 'double' 'frequency<double,std::ratio<0x01,0x01>>' constructor class 'frequency<double,std::ratio<0x01,0x01>>' declared 'explicit' source_file.cpp(27) : see reference class template instantiation 'std::common_type<frequency<double,std::ratio<0x01,0x01>>,rep>' being compiled
since can't figure out signature is, can't figure out 1 select, , gives up. consider bug in msvc's implementation of operator*
in case.
the obvious workaround make common_type<frequency<double>,rep>
able compile, possibly removing explicit
limitation on constructor. aschepler observes might smarter , more useful instead specialize common_type
:
namespace std { template <typename rep, typename period> struct common_type<frequency<rep,period>, std::chrono::duration<rep,period>> { typedef rep type; }; template <typename rep, typename period> struct common_type<std::chrono::duration<rep,period>, frequency<rep,period>> { typedef rep type; }; }
Comments
Post a Comment