【发布时间】:2018-05-11 10:55:40
【问题描述】:
我正在研究的组合算法需要大整数,作为练习,我想我会编写一个简单的 128 位整数类,但我遇到了与构造函数的一些不一致之处。
我有几个构造函数,因此您可以从另一个构造函数(使用隐式复制构造函数)或从 64 位整数或一对 64 位整数创建 uint128_t。这一切都有效,但让我感到困惑的是我可以使用这种语法:
uint128_t a = 123ull;
uint128_t b = a;
但不是:
uint128_t e = {123ull, 456ull}; // COMPILER ERROR
uint128_t f = std::make_pair(123ull, 456ull); // COMPILER ERROR
即使这些工作:
uint128_t c({123ull, 456ull});
uint128_t d(std::make_pair(123ull, 456ull));
我得到的错误是:
could not convert '{123, 345}' from '<brace-enclosed initializer list>' to 'uint128_t'
conversion from 'std::pair<long long unsigned int, long long unsigned int>' to non-scalar type 'uint128_t' requested
我可以只使用有效的语法,但我想知道我是否缺少一些简单的东西可以让uint128_t a = {1,2} 语法工作,因为这样可以更容易地将现有代码转换为使用 128位整数。
这里概述了哪些有效,哪些无效,以及课程的相关部分:
#include "uint128_t.hpp"
int main() {
uint128_t a = 123ull; // explixit constructor from uint64_t = ok
uint128_t b = a; // implicit copy constructor = ok
a = b; // assignment from uint128_t = ok
b = 123ull; // assignment from uint64_t = ok
a = {123ull, 456ull}; // assignment from pair of uint64_t = ok
b = std::make_pair(123ull, 456ull); // assignment from pair of uint64_t = ok
uint128_t c({123ull, 456ull}); // explixit constructor from pair = ok
uint128_t d(std::make_pair(123ull, 456ull));
uint128_t e = {123ull, 456ull}; // COMPILER ERROR
uint128_t f = std::make_pair(123ull, 456ull); // COMPILER ERROR
return 0;
}
#include <cstdint>
class uint128_t {
private:
uint64_t hi;
uint64_t lo;
public:
uint128_t() {}
~uint128_t() {}
uint128_t(uint64_t const& val) {
hi = UINT64_C(0);
lo = val;
}
uint128_t(std::pair<uint64_t const, uint64_t const> const& val) {
hi = val.first;
lo = val.second;
}
uint128_t const& operator=(uint128_t const&);
uint128_t const& operator=(uint64_t const);
uint128_t const& operator=(std::pair<uint64_t const, uint64_t const> const&);
}
#include "uint128_t.hpp"
uint128_t const& uint128_t::operator=(uint128_t const& other) {
this->hi = other.hi;
this->lo = other.lo;
return *this;
}
uint128_t const& uint128_t::operator=(uint64_t const val) {
this->hi = UINT64_C(0);
this->lo = val;
return *this;
}
uint128_t const& uint128_t::operator=(std::pair<uint64_t const, uint64_t const> const& val) {
this->hi = val.first;
this->lo = val.second;
return *this;
}
【问题讨论】:
-
uint128_t::uint128_t(uint64_t, uint64_t) -
你为什么一直把
ull字面量称为uint64_t?第二个错误实际上是由它引起的。你的文字是 notuint64_t。并且编译器无法将std::pair<unsigned long long, unsigned long long>转换为您的std::pair<uint64_t const, uint64_t const>,因为这将是 second 在仅允许 one 此类转换的上下文中的隐式用户定义转换。 -
@AnT 删除
ull或将其替换为 uint64_t 似乎没有什么区别。 -
@m69:那是因为您在模板参数中也有那个奇怪的
const,它仍然会强制进行第二次转换。如果您只是在代码中添加强制转换,您的std::make_pair将生成std::pair<uint64_t, uint64_t>,但您的构造函数需要std::pair<const uint64_t, const uint64_t>。这是两种不同的类型,它们会触发另一个用户定义的转换。也摆脱那个const。 coliru.stacked-crooked.com/a/cb92e1103369b38c -
@m69:它适用于
a({123,456}),但不适用于a = {123,456}或a{123,456}。后两者是list-initializations,而a({123,456})是直接初始化。
标签: c++ c++11 constructor assignment-operator std-pair