[cfe-dev] RFC on N3526 implementation

Michael Price michael.b.price.dev at gmail.com
Fri Mar 29 07:55:16 PDT 2013


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 <cstddef>

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;
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130329/fff24b49/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: n3526.diff
Type: application/octet-stream
Size: 4724 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130329/fff24b49/attachment.obj>


More information about the cfe-dev mailing list