I am trying to create an initializer_list constructor for an n-dimensional array object. I started by defining the following type traits and concepts:
#include <initializer_list>
#include <type_traits>
template <typename T, typename U>
struct is_nested_initializer_list_of : std::false_type {};
template <typename T>
struct is_nested_initializer_list_of<T, std::initializer_list<T>>
: std::true_type {};
template <typename T, typename U>
struct is_nested_initializer_list_of<T, std::initializer_list<U>>
: is_nested_initializer_list_of<T, U> {};
template <typename T, typename U>
constexpr bool is_nested_initializer_list_of_v =
is_nested_initializer_list_of<T, U>::value;
template <typename T, typename U>
concept nested_initializer_list_of = is_nested_initializer_list_of_v<T, U>;
template <typename T, typename U>
concept maybe_nested_initializer_list_of =
std::is_same_v<T, U> || nested_initializer_list_of<T, U>;
If I have defined the concept correctly, nested_initializer_list_of<T, U> should be true if U is std::initializer_list<T>, std::initializer_list<std::initializer_list<T>>, etc., and false otherwise. maybe_nest_initializer_list<T, U> should also be true if U is T.
I then defined my class as follows:
template <typename T> class NDArray {
std::vector<std::size_t> shape;
std::vector<T> vector;
public:
template <maybe_nested_initializer_list_of<T> U>
constexpr NDArray(std::initializer_list<U> il) {
...
}
};
Finally, I defined a quick main function to test the constructor:
int main() {
NDArray<int> one{1, 2};
NDArray<int> two{{1,2},{3,4}};
}
one compiles as expected, but two generates an error:
CLion inspection
No matching constructor for initialization of 'NDArray'
candidate constructor template not viable: requires single argument 'il', but 2 arguments were provided
candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
NMAKE error:
main.cpp: error C2440: 'initializing': cannot convert from 'initializer list' to 'ndarray::NDArray<int>'
test.cpp: note: No constructor could take the source type, or constructor overload resolution was ambiguous
NMAKE : fatal error U1077: 'C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1429~1.301\bin\Hostx64\x64\cl.exe' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.