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

Posted

技术标签:

【中文标题】另一个容器内的c ++容器【英文标题】:c++ container inside another container 【发布时间】:2021-01-03 03:36:55 【问题描述】:
#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

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

编译器:clang c++20

错误信息:

从 'int' 到 'Row' 的转换不可行

x2 = 10

【问题讨论】:

请创建一个minimal reproducible example - 任何拥有符合标准的编译器的人都可以编译的东西。提示:#include &lt;bits/stdc++.h&gt; 不包含标准标题。 你需要实现operator =(...) 【参考方案1】:

问题是copy initialization 比直接初始化更宽松:

> 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.

因为从int 初始化需要2 次转换(从intRow&lt;int&gt; 和从Row&lt;int&gt;Row&lt;Row&lt;int&gt;&gt;),直接初始化允许它,但复制初始化不允许。您也可以在文档示例中看到它:

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

【讨论】:

【参考方案2】:

Row<Row<int>> x2 = 10;

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

Row<Row<int>> x2 = Row<int>(10); 

来自copy-constructor reference:

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

【讨论】:

自 C++17 以来,复制初始化不一定调用复制/移动构造函数;这里有一个特殊的规则来防止第二次转换 ([over.best.ics]/4)。【参考方案3】:

这是编译器可能会为第一次调用生成的(参考cppinsights)

/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct Row<int>

  inline Row();
  
  inline Row(const Row<int> & other);
  
  inline Row(Row<int> && other);
  
  inline Row(int x)
  
    puts("Row int");
  
  
;

#endif


/* First instantiated from: insights.cpp:12 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
struct Row<Row<int> >

  inline Row();
  
  inline Row(const Row<Row<int> > & other);
  
  inline Row(Row<Row<int> > && other);
  
  inline Row(Row<int> x)
  
    puts("Row int");
  
  
;

#endif


int main()

  Row<Row<int> > x = Row<Row<int> >(Row<int>(10));

你的输出将是 Row int Row int

Row int 来自第一个模板实例化和一个来自第二个模板实例化

当你尝试时

Row<Row<int>> x2 = 10;

编译器将10转换为int,但它可以找到可以直接将int转换为Row&lt;Row&lt;int&gt;&gt;的实例化。这将需要 2 次转换。

所以要么你自己提供一个转换,要么使用直接初始化。

【讨论】:

以上是关于另一个容器内的c ++容器的主要内容,如果未能解决你的问题,请参考以下文章

@FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本

颤振:单击该小部件内的按钮后如何将小部件更改为另一个小部件

包含另一个地图的对象的C ++地图插入问题

C# Azure.Storage.Blobs SDK 如何列出和压缩容器中的所有文件并将压缩文件存储在另一个容器中

无法连接到 docker 容器内的 SQL Server

c++ segfault 在一个平台(MacOSX)但不是另一个(Linux)