c++template-argument-deductionstdarraylist-initialization

Why does template deduction for a nested std::array with one element result in a one dimensional std::array?


The following code compiles successfully with clang and gcc. Naively, I would have expected a2 to have type std::array<std::array<int, 1>, 1>.

#include <array>

auto a1 = std::array{1};
auto a2 = std::array{std::array{1}};
static_assert(std::same_as<decltype(a1), std::array<int, 1>>);  // passes
static_assert(std::same_as<decltype(a1), decltype(a2)>);    // passes, but I expect this to fail

So why does template deduction for a nested std::array with one element result in a one dimensional std::array?


Solution

  • CTAD also takes into account copy constructor.

    CTAD rules states (emphasis mine)

    Template argument deduction and overload resolution is then performed for initialization of a fictional object of hypothetical class type, whose constructor signatures match the guides (except for return type) for the purpose of forming an overload set, and the initializer is provided by the context in which class template argument deduction was performed, except that the first phase of list-initialization (considering initializer-list constructors) is omitted if the initializer list consists of a single expression of type (possibly cv-qualified) U, where U is a specialization of C or a class derived from a specialization of C.

    which "de-prioritize" std::initializer_list.