以下代码使用带有 C++17 集的 gcc 7.1.0 进行编译,但不使用 C++14 集(或 Visual Studio 2017)进行编译。很容易重现Wandbox https://wandbox.org/permlink/b8QJGuSPUcTPRuFM.
必须做什么才能使其与 C++11/14 一起工作?
#include <iostream>
#include <chrono>
int main()
{
struct Convert
{
operator std::chrono::milliseconds()
{
std::cout << "operator std::chrono::milliseconds" << std::endl;
return std::chrono::milliseconds(10);
}
operator int64_t ()
{
std::cout << "operator int64_t" << std::endl;
return 5;
}
};
Convert convert;
std::chrono::milliseconds m(convert);
std::cout << m.count() << std::endl;
int64_t i(convert);
std::cout << i << std::endl;
}
让我们首先了解为什么这在 C++14 中不起作用。有两个相关的 c'torsstd::chrono::duration http://en.cppreference.com/w/cpp/chrono/duration/duration (which std::chrono::milliseconds
别名为):
duration( const duration& ) = default;
template< class Rep2 >
constexpr explicit duration( const Rep2& r );
模板化的参数更适合类型参数Convert
。但它只会参与重载决策,如果Rep2
(a.k.a Convert
) 可以隐式转换为以下表示类型std::chrono::duration
. For milliseconds
, 那是long
在Wandbox上。你的int64_t
转换运算符使隐式转换成为可能。
但这是问题所在。对此隐式转换的检查不考虑转换成员函数的 cv 限定符。因此选择了重载,但它接受 const 引用。并且您的用户定义的转换运算符不是const
合格的!@Galik https://stackoverflow.com/users/3807729/galik在您帖子的评论中指出了这一点。因此,转换在 c'tor 内失败milliseconds
.
那么如何解决呢?两种方式:
标记转换运算符const
。然而,这将选择转换为int64_t
对彼此而言m
and i
.
将转换标记为int64_t
as explicit
。现在,模板化重载将不会参与重载决策m
.
最后,为什么这在 C++17 中有效?这将保证复制省略。自从你的Convert
有一个转换为std::chrono::milliseconds
,它用于初始化m
直接地。它的细节涉及甚至不需要选择复制构造函数,只需稍后将其删除即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)