Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std中的完美转发::使_独一无二<;SomeWrapper<;T>&燃气轮机;不太完美_C++ - Fatal编程技术网

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
的模板参数推断失败。这是我的

  • 参数P,其A是一个大括号的init list,但P不是
    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个参数发送的观点是一个打字错误,我刚刚更新了我的帖子,对此表示抱歉。但仍然没有编译