另一个容器内的c ++容器

Veg*_*eta 5 c++ c++20

#include <bits/stdc++.h>

template <typename T>
struct Row {
    Row() { puts("Row default"); }
    Row(const Row& other) { puts("Row copy"); }
    Row(Row&& other) { puts("Row move"); }
    Row(T x) { puts("Row int"); }
};

int main() {
  Row<Row<int>> x (10); // this works
  Row<Row<int>> x2 = 10; // error
}
Run Code Online (Sandbox Code Playgroud)

为什么代码不起作用?我知道第一个执行直接初始化,第二个是复制初始化,但是当涉及到容器内的容器时,我对我来说并不容易。

编译器:clang c++20

错误信息:

没有从“int”到“Row<Row>”的可行转换

行<行> x2 = 10

Sla*_*ica 10

问题是复制初始化不如直接初始化宽松:

> In addition, the implicit conversion in copy-initialization must produce T
  directly from the initializer, while, e.g. direct-initialization expects
  an implicit conversion from the initializer to an argument of T's constructor.
Run Code Online (Sandbox Code Playgroud)

由于初始化 fromint需要 2 次转换(从inttoRow<int>和 from Row<int>to Row<Row<int>>),直接初始化允许,但复制初始化不允许。您也可以在文档示例中看到它:

struct S { S(std::string) {} }; // implicitly convertible from std::string
S s("abc"); // OK: conversion from const char[4] to std::string
S s = "abc"; // Error: no conversion from const char[4] to S
S s = "abc"s; // OK: conversion from std::string to S
Run Code Online (Sandbox Code Playgroud)


Jar*_*vis 1

\n
Row<Row<int>> x2 = 10;\n
Run Code Online (Sandbox Code Playgroud)\n

而不是调用赋值运算符,而是发生您提到的复制初始化。复制初始化调用对象的复制(或移动)构造函数,这要求您通过引用作为参数传递对象,这对于int您传递的 10 显然是不可能的。为了使其工作,您必须提供一个有效的类型来复制:

\n
Row<Row<int>> x2 = Row<int>(10); \n
Run Code Online (Sandbox Code Playgroud)\n

来自复制构造函数参考

\n
\n

类 T 的复制构造函数是非模板构造函数,其第一个参数为 T&\xe2\x80\x8d、const T&\xe2\x80\x8d、volatile T&\xe2\x80\x8d 或 const vola

\n
\n