C++ 以std::pair作为参数的构造函数:ta({1,2})起作用,ta={1,2}不';T

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

我正在研究的一个组合算法需要大整数,作为练习,我想写一个简单的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_对(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