Why are constructors with arrays and constructors with arrays of arrays ambiguous in C++?

I want to make my own struct for a 3×3 Matrix. I want to allow construction via components/elements or by "rows".

So either you provide a std::array<float, 9> or a std::array<std::array<float, 3>, 3>

However when defining the struct like this with the following constructors:

struct Matrix3x3
{
    Matrix3x3(std::array<float, 9> components) { }

    Matrix3x3(std::array<std::array<float, 3>, 3> rows) { }
};

Then the second constructor is ambiguos with the first. Meaning that you can call the second constructor like this

Matrix3x3{ {{ {{1.f, 2.f, 3.f}}, {{4.f, 5.f, 6.f}}, {{7.f, 8.f, 9.f}} }} };

without any problems, however calling the first constructor like this

Matrix3x3{ {{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f}} };

will give the following message and error:

message : No constructor could take the source type, or constructor overload resolution was ambiguous
error C2440: '<function-style-cast>': cannot convert from 'initializer list' to 'ArrayTest'

And Visual Studio tells me that there is "more than one instance of constructor … matches the argument list".

Note that Im intentionally not omitting any braces in my calls, since this question is not about whether or not I could omit some of those braces and why I could do so, but specifically why those constructors are ambiguous.

I tested doing the same thing but with an array of ints( because its easier to work with) and a length of one. Consider:

struct ArrayTest
{
    ArrayTest(std::array<int, 1> arrayOfFloats) { }

    ArrayTest(std::array<std::array<int, 1>, 1> arrayOfArraysOfInts) { }
};

Then all of the following constructor calls are valid and will compile for each constructor:

auto test1 = ArrayTest{ {1} };

auto test2 = ArrayTest{ { {1} } };

auto test3 = ArrayTest{ { { {1} } } };

However I dont quite understand why the first call is valid for the array-of-arrays constructor and why the third call is valid for the simple array constructor.

And the more important remaining question is: How do I solve this problem?

Source: Windows Questions C++

LEAVE A COMMENT