RFC on N3526 implementation

I’ve attached the diff (generated by git). It currently does not contain updated tests, as I was unable to get the lit framework to work properly for me. I’ve pasted a sample program below. You can enable the proposed syntax changes with ‘-fproposal-n3526’.

I’m specifically looking for comments on whether there are any corner cases that I may have missed, or if there are other types of tests that should eventually be included. I am not looking to have this code committed yet (at least not to the clang trunk), thus why I didn’t send it to cfe-commits. I’m also curious if there is a procedure in place for adopting experimental implementations of proposals, particularly as it applies to enabling/disabling those implementations (I’m not sure I did it “correctly” here).

#include

using namespace std;

namespace n3526 {

namespace Example4 {

// A pared-down array implementation
template <class T, size_t N, size_t … Rest>
struct array
{
typedef array<T, Rest…> elem_type;
elem_type _elems[N];
};

template <class T, size_t N>
struct array<T, N>
{
typedef T elem_type;
elem_type _elems[N];
};
}

namespace Example5 {

// A slightly better, pared-down array implementation
template <class T, size_t N, size_t … Rest>
struct array
{
typedef typename array<T, Rest…>::value_type value_type[N];
value_type _elems;
};

template <class T, size_t N>
struct array<T, N>
{
typedef T value_type[N];
value_type _elems;
};
}
}

int main (int argc, char ** argv)
{
// Example 1
{
int aggr_array[2] = {1, 2};

struct aggr_t {
int a;
int b;
} instance = {3, 4};
}

// Example 2
{
int aggr_array[2][2] = {{1, 2}, {3, 4}};

struct aggr_t {
struct {
int a;
int b;
} x, y;
} instance = {{1, 2}, {3, 4}};
}

// Example 3
// ‘bad’ will fail unless -fproposal-n3526 is provided
{
struct aggr_t {
int a;
int b;
} array_of_aggr[2] = {{1, 2}, {3, 4}};

struct aggr_ex_t {
int x[2][2];
};

aggr_ex_t bad = {{1, 2}, {3, 4}}; // Error: Too many initializers, see below for details
aggr_ex_t good = {{{1, 2}, {3, 4}}};
}

// Example 4
{
// Using this (n3526::Example4::array) multidimensional array
using namespace n3526::Example4;

// 1-dimension, everything works as expected
int _a[2] = {0, 0};
array<int, 2> a = {0, 0};

// 2-dimensions, extra braces are needed
int _b[2][2] = {{1, 1}, {2, 2}};
array<int, 2, 2> b = {{{1, 1}, {2, 2}}};

// 3-dimensions, this begins to get out-of-hand
int _c[2][2][2] = {{{3, 3}, {4, 4}}, {{5, 5}, {6, 6}}};
array<int, 2, 2, 2> c = {{{{{3, 3}, {4, 4}}}, {{{5, 5}, {6, 6}}}}};
}

// Example 5
{

// Using this (n3526::Example5::array) multidimensional array
using namespace n3526::Example5;

// 1-dimension, everything works as expected
int _a[2] = {0, 0};
array<int, 2> a = {0, 0};

// 2-dimensions, extra braces are needed
int _b[2][2] = {{1, 1}, {2, 2}};
array<int, 2, 2> b = {{{1, 1}, {2, 2}}};

// 3-dimensions, this begins to get out-of-hand
int _c[2][2][2] = {{{3, 3}, {4, 4}}, {{5, 5}, {6, 6}}};
array<int, 2, 2, 2> c = {{{{3, 3}, {4, 4}}, {{5, 5}, {6, 6}}}};
}

// Example 6
// ‘good’ should only succeed with -fproposal-n3526
// ‘still-bad’ should fail in any situation
{
struct aggr_ex_t {
int x[2][2];
};

aggr_ex_t fully_braced = {{{1, 2}, {3, 4}}};

aggr_ex_t good = {{1, 2}, {3, 4}}; // Behaves as if the
// initializer list had
// been {{{1, 2}, {3, 4}}}

// Would still be an error per paragraphs 8.5.1.6 and 8.5.1.11 since the
// initializer-list would be equivalent to {{{1, 2}, {3, 4}, {5, 6}}}
// and would have too many initialization-clauses.
aggr_ex_t still_bad = {{1, 2}, {3, 4}, {5, 6}};
}

// Example 7
// ‘good’ and ‘also_good’ should only succeed with -fproposal-n3526
{
struct aggr_ex_t {
int x[2][2];
};

struct aggr_more_t {
aggr_ex_t _a;
};

aggr_more_t fully_braced = {{{{1, 2}, {3, 4}}}};

aggr_more_t good = {{{1, 2}, {3, 4}}}; // Both behave as if the
aggr_more_t also_good = {{1, 2}, {3, 4}}; // initializer lists had
// been {{{{1, 2}, {3, 4}}}}
}

// Example 8 (appears in standards text)
// ‘a2’ and ‘a3’ should only succeed with -fproposal-n3526
{
struct S {
int x[2][2];
};

struct A {
S s;
};

A a1 = {{{{1, 2}, {3, 4}}}};
A a2 = {{{1, 2}, {3, 4}}};
A a3 = {{1, 2}, {3, 4}};
A a4 = {1, 2, 3, 4};
}

//////////////////// Tests not appearing in the proposal //////////////////////

// constexpr tests
// ‘a2’ and ‘a3’ should only succeed with -fproposal-n3526
{
struct S {
int x[2][2];
};

struct A {
S s;
};

constexpr A a1 = {{{{1, 2}, {3, 4}}}};
constexpr A a2 = {{{1, 2}, {3, 4}}};
constexpr A a3 = {{1, 2}, {3, 4}};
constexpr A a4 = {1, 2, 3, 4};
}

// non-builtin type tests (no initializer-list ctor)
// ‘a2’ and ‘a3’ should only succeed with -fproposal-n3526
{
struct Type {
Type(int, const char*, bool) { /* … */ }
};

struct S {
Type x[2][2];
};

struct A {
S s;
};

// TODO: These initializer_lists didn’t seem to automatically call the matching constructor for ‘Type’, so I had to be explicit

A a1 = {{{{Type{1, “One”, true}, Type{2, “Two”, false}}, {Type{3, “Three”, true}, Type{4, “Four”, false}}}}};
A a2 = {{{Type{1, “One”, true}, Type{2, “Two”, false}}, {Type{3, “Three”, true}, Type{4, “Four”, false}}}};
A a3 = {{Type{1, “One”, true}, Type{2, “Two”, false}}, {Type{3, “Three”, true}, Type{4, “Four”, false}}};
A a4 = {Type{1, “One”, true}, Type{2, “Two”, false}, Type{3, “Three”, true}, Type{4, “Four”, false}};
}

return 0;
}

n3526.diff (4.61 KB)