5

Initially I started trying to initialize a vector of const char*[3] with an initilizer-list on declaration

vector<const char*[3]> v = { { "a", "b", "c" } };

And this gives the error

matrix must be initialized with a brace-enclosed initializer

I thought it might be due to the const char*, although it seemed odd, and changed it into strings

vector<string[3]> v = { { "a", "b", "c" } };

But the error persists. I tried several combinations of braces to no avail. Is it actually possible to initialize this structure on declaration with an initializer-list?

Marek R
  • 32,568
  • 6
  • 55
  • 140
ronaldo
  • 455
  • 3
  • 9
  • 3
    What is the purpose of the vector? Do you want a single vector with three single string elements (i.e. `std::vector`)? Or do you want a vector where each element is an array of three strings (i.e. `std::vector>`)? – Some programmer dude Sep 16 '18 at 09:14
  • I don't have an actual answer, but C arrays are second class citizens at best in the C and C++ type systems, so don't be surprised if most of the fancy stuff doesn't work with them. Try with `std::array`. – Matteo Italia Sep 16 '18 at 09:15
  • @Someprogrammerdude I actually want the second option, a vector that contains arrays of 3 const char*/string elements. I was also thinking of using std::array (and have other solutions), but still wanting to know why this is not possible to do, or if it actually is possible and I don't know how to do it. – ronaldo Sep 16 '18 at 09:21
  • If you can use `std::array` instead of `std::vector` it would compile `std::array v = { { "a", "b", "c" } };` – Killzone Kid Sep 16 '18 at 09:47
  • You forgot to specify what compiler and version gives that error. I have never seen an error like that. What is "matrix"? – underscore_d Sep 18 '18 at 18:34

2 Answers2

7

It fails to compile because std::vector requires its T to be CopyAssignable. No matter its RHS, this statement wouldn't not compile:

vector<const char*[3]> v = { { "a", "b", "c" } }; // Error

just as this wouldn't compile either:

std::vector<const char*[3]> v;
const char* charPtrArr[3] { "a", "b", "c" };
v.push_back(charPtrArr); // Error

This is just a particular case of the fact that C-style arrays are not assignable, demonstrated in code directly by using static_assert:

static_assert(std::is_copy_assignable<const char*[3]>()); // Error

or more generally I guess:

static_assert(std::is_copy_assignable<int[]>()); // Error

If you really wanted a std::vector of arrays of size 3 holding char pointers, then this is the error-free C++11 way to go about it:

vector<array<const char*, 3>> v = { { "a", "b", "c" }, { "d", "e", "f"} };
Geezer
  • 5,600
  • 18
  • 31
  • 1
    So, the problem is the same with string[3], because string is CopyAssignable, but string[3] is not. Yeah, that makes sense. I wrongly thought of it when I changed const char* into string. Thanks for the explanation. – ronaldo Sep 16 '18 at 09:50
  • 1
    Absolutely right, the *native array* itself is the problem. – Geezer Sep 16 '18 at 09:52
4

Problem is that C-style array can't be passed by copy or moved in function argument. As a result this code will not work

vector<const char*[3]> v;
const char* item[3] { "a", "b", "c" };
v.push_back(item); // will not compile

https://wandbox.org/permlink/LumvUzPnYWew7uMu
Basically this is the same problem, but initialization list is involved.

C++11 give you simple solution for your problem:

vector<array<const char*, 3>> v { { "a", "b", "c" }, { "d", "e", "f"} };

https://wandbox.org/permlink/IHNoSrH9BWV1IUoQ

Marek R
  • 32,568
  • 6
  • 55
  • 140