C++ 以std::pair作为参数的构造函数:ta({1,2})起作用,ta={1,2}不';T
我正在研究的一个组合算法需要大整数,作为练习,我想写一个简单的128位整数类,但是我遇到了一些与构造函数不一致的问题 我有几个构造函数,因此您可以从另一个构造函数(使用隐式复制构造函数)或64位整数或一对64位整数创建C++ 以std::pair作为参数的构造函数:ta({1,2})起作用,ta={1,2}不';T,c++,c++11,constructor,assignment-operator,std-pair,C++,C++11,Constructor,Assignment Operator,Std Pair,我正在研究的一个组合算法需要大整数,作为练习,我想写一个简单的128位整数类,但是我遇到了一些与构造函数不一致的问题 我有几个构造函数,因此您可以从另一个构造函数(使用隐式复制构造函数)或64位整数或一对64位整数创建uint128\u t。这一切都是可行的,但让我困惑的是,我可以使用以下语法: uint128\u t a=123ull; uint128_t b=a; 但不是: uint128\u t e={123ull,456ull};//编译错误 uint128_t f=std::make
uint128\u t
。这一切都是可行的,但让我困惑的是,我可以使用以下语法:
uint128\u t a=123ull;
uint128_t b=a;
但不是:
uint128\u t e={123ull,456ull};//编译错误
uint128_t f=std::make_对(123ull,456ull);//编译错误
尽管这些措施有效:
uint128_t c({123ull,456ull});
uint128_t d(标准:制造成对(123ull,456ull));
我得到的错误是:
无法将“{123,345}”从“”转换为“uint128\t”
请求从“std::pair”转换为非标量类型“uint128\t”
我可以只使用有效的语法,但我想知道我是否缺少一些简单的东西,可以让uint128\u t a={1,2}
语法起作用,因为这样可以更容易地将现有代码转换为128位整数
以下概述了课程中哪些有效,哪些无效,以及相关部分:
#包括“uint128水电站”
int main(){
uint128\u t a=123ull;//从uint64\u t=ok解释构造函数
uint128\u t b=a;//隐式复制构造函数=ok
a=b;//来自uint128的赋值\u t=ok
b=123ull;//来自uint64的赋值\u t=ok
a={123ull,456ull};//从uint64\u t=ok对进行赋值
b=std::make_pair(123ull,456ull);//从uint64_t的对进行赋值=ok
uint128_t c({123ull,456ull});//从pair=ok解释构造函数
uint128_t d(标准:制造成对(123ull,456ull));
uint128_t e={123ull,456ull};//编译器错误
uint128_t f=std::make_pair(123ull,456ull);//编译器错误
返回0;
}
#包括
uint128类{
私人:
uint64_t hi;
uint64_t lo;
公众:
uint128_t(){}
~uint128_t(){}
uint128_t(uint64_t const&val){
hi=UINT64_C(0);
lo=val;
}
uint128_t(标准::成对常数和值){
hi=val.first;
lo=val.second;
}
uint128_t const&运算符=(uint128_t const&);
uint128常量和运算符=(uint64常量);
uint128_t常量和运算符=(标准::对常量和);
}
#包括“uint128水电站”
uint128常量和uint128常量::运算符=(uint128常量和其他){
this->hi=other.hi;
此->lo=other.lo;
归还*这个;
}
uint128_t const&uint128_t::operator=(uint64_t const val){
此->hi=UINT64_C(0);
这->lo=val;
归还*这个;
}
uint128_t常量和uint128_t::运算符=(标准::对常量和值){
此->hi=val.first;
这->lo=val.second;
归还*这个;
}
您需要提供相应的构造函数
uint128_t::uint128_t(uint64_t,uint64_t)//uint128_t x={123ull,456ull};
uint128_t::uint128_t(const std::pair&val)//uint128_t x=std::make_-pair(123ull,456ull)*
请注意,在第一次拷贝初始化中,
ull
并不总是等于uint64\t
uint128_t e = {123ull, 456ull};
uint128_t f = std::make_pair(123ull, 456ull);
您正在使用多值列表初始化非聚合类。根据列表初始化规则,在这种情况下,编译器将考虑<代码> STD::IngaliSerixListBase/Cuth>构造函数,然后将考虑类中的两个参数构造函数。类中不存在匹配的构造函数,因此初始化失败
您可能希望编译器将{123ull,456ull}
转换为std::pair
,然后使用该std::pair
初始化e
。但是C++中的列表初始化不考虑这个初始化路径。(请注意,顺便说一句,这看起来也像两个用户定义的转换序列,见下文。)
您的第二个副本初始化
uint128_t e = {123ull, 456ull};
uint128_t f = std::make_pair(123ull, 456ull);
失败的原因与以下简化代码失败的原因相同
struct A { A(int) {} };
struct B { B(const A &) {} };
int main() {
B b1(42); // OK
B b2 = 42; // Error
}
上述复制初始化需要在其转换序列中进行两次隐含的用户定义转换:从int
到A
,然后从A
到B
。即使存在这样的转换,也不允许隐式应用其中的两个转换。复制初始化中最多允许一次隐式用户定义转换
在本例中,您请求从std::pair
转换为std::pair
(构造函数参数类型),然后从std::pair
转换为uint128\t
——两次转换。这些转换是存在的,但一行两个太多了
即使您确保
std::make_pair
的参数具有uint64_t
类型,那些std::pair
中的const
限定符仍将强制进行额外的转换。您的make\u pair
调用将生成一个std::pair
值,该值必须转换为std::pair
,然后转换为uint128\u t
uint128\u t::uint128\u t(uint64\u t,uint64\u t)
为什么您一直将ull
文字称为uint64\u t
?第二个错误实际上是由此引起的。您的文字不是uint64\u t
。而且编译器无法将std::pair
转换为您的std::pair
,因为这将是在只允许一次这种转换的上下文中的第二次隐式用户定义转换。@AnT删除ull
或将其替换为对uint64的强制转换似乎没有什么区别。@m69:这是因为您也有这种转换模板参数中奇异的const
,