我创建了一个频率类模板,旨在与std::chrono::持续时间 http://en.cppreference.com/w/cpp/chrono/duration。频率对象存储每单位持续时间的周期数(均使用其类型的模板参数)。这个想法是,将频率乘以持续时间会生成 Rep 类型的对象。这是类定义。除了相关成员之外,我省略了所有成员。
#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.
};
问题(我认为)是 std::chrono::duration 也会重载 * 运算符,如下所示:
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 );
根据参考参数 http://en.cppreference.com/w/cpp/chrono/duration,这些方法中的每一个
将持续时间 d 转换为 Rep 为 Rep1 和 Rep2 之间通用类型的持续时间,并将转换后的刻度数乘以 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 中的重载?我知道我可以通过不使用运算符重载并编写不同名称的方法来解决问题,但如果可能的话,我想更好地了解这里发生的情况。 (而且重载更方便。)
另外,如果这个问题重复,我深表歉意,但搜索后我找不到类似的内容。