C++ std中的完美转发::使_独一无二<;SomeWrapper<;T>&燃气轮机;不太完美
鉴于以下类型:C++ std中的完美转发::使_独一无二<;SomeWrapper<;T>&燃气轮机;不太完美,c++,C++,鉴于以下类型: 结构点 { int x; int-y; 点(intx,inty):x{x},y{y} }; 类小部件 { 公众: std::字符串名; 小部件(std::string name):名称{name}{} }; 模板 结构数据持有者 { T值; 数据持有者(T值):值{value}{} }; 此代码为何编译: auto compiles = std::make_unique<DataHolder<int>>(42); auto alsoCompiles =
结构点
{
int x;
int-y;
点(intx,inty):x{x},y{y}
};
类小部件
{
公众:
std::字符串名;
小部件(std::string name):名称{name}{}
};
模板
结构数据持有者
{
T值;
数据持有者(T值):值{value}{}
};
此代码为何编译:
auto compiles = std::make_unique<DataHolder<int>>(42);
auto alsoCompiles = std::make_unique<DataHolder<std::string>>("Hi");
autocompiles=std::make_unique(42);
auto-alsoCompiles=std::使_唯一(“Hi”);
而该代码不:
auto doesnt = std::make_unique<DataHolder<Point>>({20, 21});
auto alsoDoesnt = std::make_unique<DataHolder<Widget>>("Hello");
auto-doesnt=std::使_唯一({20,21});//C2672“std::make_unique”:未找到匹配的重载函数,C7627“初始值设定项列表”:不是“_类型”的有效模板参数
auto alsoDoesnt=std::使_唯一(“Hello”);//C2664“DataHolder::DataHolder(T)”:无法将参数1从“常量字符[6]”转换为“T”
std::make_unique()
如何确定是否可以在SomeWrapper
中构造T
?在这种情况下,int
和std::string
有什么特别之处?我怎样才能让我的类型以同样的方式工作
此代码为何编译:
auto compiles = std::make_unique<DataHolder<int>>(42);
auto alsoCompiles = std::make_unique<DataHolder<std::string>>("Hi");
std::make_unique({20,21})
不起作用,因为像{20,21}
这样的带括号的init列表没有类型,std::make_unique
的模板参数推断失败。这是我的
std::initializer_list
、对一个参数的引用(可能是cv限定的)或对数组的引用:DataHolder
有一个构造函数使用Widget
,“Hello”
是一个const char[6]
,它可以衰减为const char*
,然后需要两个用户定义的转换,一个从const char*
转换为std::string
,一个从std::string
转换为Widget
,但在一个隐式转换序列中只允许一个用户定义的转换。(类似地,DataHolder(“Hello”)
也不起作用。)
如果您直接通过点
和std::string
,它们将正常工作
auto doesnt = std::make_unique<DataHolder<Point>>(Point{20, 21});;
auto alsoDoesnt = std::make_unique<DataHolder<Widget>>(std::string{"Hello"});
注意std::make_惟一({20,21})由于上述原因,代码>仍然不起作用。但是你可以做std::make_unique(20,21)
相反,20
和21
被禁止进入点的构造函数,取两个int
s,然后工作正常。类似地,对于std::make_unique(“Hello”)
,将“Hello”
转发给Widget
的构造函数,使用std::string
,“Hello”
可以隐式转换为std::string
,然后工作正常。std::make_unique(“Hello”)
需要两次转换,一个从const char*
到std::string
,另一个到Widget
。只允许一次隐式转换
std::make_unique(20,21)
不起作用,因为它与调用DataHolder(20,21)
相同,但是DataHolder
只接受一个参数
您的前两个示例只需要一个或不需要隐式转换,因此可以正常工作
要使这些工作正常,您需要数据持有者
将其构造函数参数转发到值
:
template <typename ...Args>
DataHolder(Args&& ... args) : value {std::forward<Args>(args)...} { }
模板
数据持有者(Args&&…Args):值{std::forward(Args)…}{
DataHolder
不会将c-tor的参数转发给实际的c-tor(尝试类似于模板DataHolder(Args&&…Args):value{Args…}{}
)。这两个答案现在都有您要求的示例,因此我不会重复它们。其想法是,您可能希望延迟任何转换,并将参数一直传递到最后一个(最深的)构造函数。为了解决大括号初始化问题,对于点
,您可以使用std::make_unique(20,21)
(就像您在未编辑的问题中所做的那样)。作为两个参数发送的点
是一个输入错误,我刚刚更新了我的帖子,对此表示抱歉。但是仍然没有编译。谢谢你的回答,它非常有用!根据@YiFei在我的原始帖子中的建议,有没有办法修改数据持有者
以进一步传递参数?我不完全理解他们的建议though@CoolBots答案修改了。作为2个参数发送的观点是一个打字错误,我刚刚更新了我的帖子,对此表示抱歉。但仍然没有编译