User overloaded operator * with std :: chrono :: duration

I created a frequency class template designed to work with std :: chrono :: duration . The Frequency object stores the number of cycles per unit time (both use template parameters for their types). The idea is that multiplying the frequency by the duration creates an object of type Rep. Here is the class definition. I missed everything except the 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; ///> The number of cycles per period.
};

The problem (I think) is that std :: chrono :: duration also overloads the * operator as 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 to cppreference , each of these methods

Converts a duration d to one whose rep is a common type between Rep1 and Rep2, and multiplies the number of ticks after the conversion by s.

, . :

Frequency<double> f{60.0};
duration<double> d{1.0};
double foo = f * d;

- VS2013:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\type_traits(1446) : error C2446: ':' : no conversion from 'double' to 'Frequency<double,std::ratio<0x01,0x01>>'
        Constructor for class 'Frequency<double,std::ratio<0x01,0x01>>' is declared 'explicit'
        source_file.cpp(27) : see reference to class template instantiation 'std::common_type<Frequency<double,std::ratio<0x01,0x01>>,Rep>' being compiled
        with
        [
            Rep=double
        ]

1446 - VS std::common_type.

, , , std:: chrono:: duration? , , , , , . ( , .)

, , , .

+4
1

:

Frequency<double> f{60.0};
duration<double> d{1.0};
double foo = f * d;

: ", operator*, Frequency<double> std::chrono::duration<double>. operator*? ,

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 );

, . :

Rep operator *(const Frequency<Rep, Period>& f, const duration<Rep, Period> d)

:

error C2446: ':' : no conversion from 'double' to 'Frequency<double,std::ratio<0x01,0x01>>'
        Constructor for class 'Frequency<double,std::ratio<0x01,0x01>>' is declared 'explicit'
        source_file.cpp(27) : see reference to class template instantiation 'std::common_type<Frequency<double,std::ratio<0x01,0x01>>,Rep>' being compiled

, , , , . ​​ MSVC operator* .

common_type<Frequency<double>,Rep> , , explicit . aschepler , 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;
    };
}
+3

Source: https://habr.com/ru/post/1543112/


All Articles