Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ container inside another container

Tags:

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
}

Why the code doesn't work? I know that first one performs direct initialization and the second one is copy initialization but still when it comes to container inside a container I doesn't get easy for me.

compiler: clang c++20

Error message:

no viable conversion from 'int' to 'Row<Row >'

Row<Row> x2 = 10

like image 669
Vegeta Avatar asked Jan 03 '21 03:01

Vegeta


2 Answers

Problem is that copy initialization is less permissive than direct 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.

as initialization from int requires 2 conversions (from int to Row<int> and from Row<int> to Row<Row<int>>), direct initialization allows it but copy initialization does not. You can see it in documentation example as well:

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
like image 75
Slava Avatar answered Oct 05 '22 14:10

Slava


In

Row<Row<int>> x2 = 10;

rather than assignment operator being invoked, the copy-initialisation happens which you mentioned as well. Copy-initialisation calls the copy (or move) constructor of the object, which requires you to pass the object by reference as an argument, which is clearly not possible with the int 10 that you are passing. To make it work, you would have to provide a valid type to copy from:

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

From the copy-constructor reference:

A copy constructor of class T is a non-template constructor whose first parameter is T&‍, const T&‍, volatile T&‍, or const vola

like image 44
Jarvis Avatar answered Oct 05 '22 14:10

Jarvis