带有std::chrono::duration的用户定义重载操作符*
User-defined overloaded operator * with std::chrono::duration
我创建了一个Frequency类模板,打算与std::chrono::duration一起工作。Frequency对象每单位持续时间存储许多周期(两者都使用其类型的模板参数)。其思想是将Frequency乘以持续时间产生类型为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 );
根据cppreference,这些方法
将持续时间d转换为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.0VCINCLUDEtype_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行是std::common_type
的VS实现。
另外,如果这个问题是重复的,我很抱歉,但我在搜索后无法找到任何类似的内容。
在此代码中:
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;
};
}
相关文章:
- 不同翻译单元中不可重载的非内联函数定义
- 在运算符重载定义中使用成员函数(const错误)
- 重载虚拟行为是否定义良好?
- 为私有结构定义双参数运算符重载
- C++:对函子重载调用运算符的未定义引用
- 指向重载静态成员的函数指针 - 在unique_ptr中用作自定义删除器
- 自定义运算符重载C++,无开销
- 运算符重载以显示用户定义的数据类型
- std::begin-类型特征中未考虑用户定义的重载
- 在priority_queue的自定义类中重载比较运算符
- 重载C++中的[]运算符以支持自定义设置函数
- 运算符的歧义错误<<自定义 std::ostream 子类中的重载
- 重载自定义类型的 std::to_string 和 std::to_chars?
- 当模板重载可用时,检查是否存在函数的自定义重载
- 定义重载C++函数模板的原型时,使用其名称引用以前的定义是否合法?
- 自定义重载运算符<<带有 log4cxx
- 为两个类定义重载的强制转换运算符,这两个类之间具有循环依赖关系
- 在类外部定义重载流出操作符
- 带有std::chrono::duration的用户定义重载操作符*
- 使用C++数组输入定义重载函数是安全的