Populate std::array with non-default-constructible type (no variadic templates)

前端 未结 2 1770
忘掉有多难
忘掉有多难 2021-01-07 06:10

Suppose I have a type A with no default constructor:

struct A
{
  int x;
  A(int x) : x(x) {}
};

I want to make an std::

2条回答
  •  北海茫月
    2021-01-07 07:01

    Here's another way which allows an arbitrary range of inputs to the generator:

    Here's the use case:

    /// generate an integer by multiplying the input by 2
    /// this could just as easily be a lambda or function object
    constexpr int my_generator(int x) {
        return 2 * x;
    }
    
    int main()
    {
        // generate a std::array containing the values
        // 0 - 126 inclusive (the 64 acts like an end() iterator)
        static constexpr auto arr = generate_array(range(),
                                                   my_generator);
    
        std::copy(arr.begin(), arr.end(), std::ostream_iterator(std::cout, ", "));
        std::cout << std::endl;
    }
    

    Here's the boilerplate to allow it to work

    #include 
    #include 
    #include 
    #include 
    #include 
    
    /// the concept of a class that holds a range of something
    /// @requires T + 1 results in the next T
    /// @requires Begin + 1 + 1 + 1.... eventually results in Tn == End
    template
    struct range
    {
        constexpr T begin() const { return Begin; }
        constexpr T end() const { return End; }
    
        constexpr T size() const { return end() - begin(); }
        using type = T;
    };
    
    /// offset every integer in an integer sequence by a value
    /// e.g offset(2, <1, 2, 3>) -> <3, 4, 5>
    template
    constexpr auto offset(std::integer_sequence)
    {
        return std::integer_sequence();
    }
    
    /// generate a std::array by calling Gen(I) for every I in Is
    template
    constexpr auto generate_array(std::integer_sequence, Gen gen)
    {
        return std::array {
            gen(Is)...
        };
    }
    
    /// generate a std::array by calling Gen (x) for every x in Range
    template
    constexpr auto generate_array(Range range, Gen&& gen)
    {
        using T = decltype(gen(range.begin()));
        auto from_zero = std::make_integer_sequence();
        auto indexes = offset(from_zero);
        return generate_array(indexes, std::forward(gen));
    }
    
    /// generate an integer by multiplying the input by 2
    constexpr int my_generator(int x) {
        return 2 * x;
    }
    
    int main()
    {
        static constexpr auto arr = generate_array(range(),
                                                   my_generator);
    
        std::copy(arr.begin(), arr.end(), std::ostream_iterator(std::cout, ", "));
        std::cout << std::endl;
    }
    

    here's the code bloat as viewed prior to assembly:

    .LC0:
        .string ", "
    main:
    ;; this is the start of the code that deals with the array
        pushq   %rbx
        movl    main::arr, %ebx
    .L2:
        movl    (%rbx), %esi
        movl    std::cout, %edi
        addq    $4, %rbx
    ;; this is the end of it
    
    ;; all the rest of this stuff is to do with streaming values to cout
        call    std::basic_ostream >::operator<<(int)
        movl    $2, %edx
        movl    $.LC0, %esi
        movl    std::cout, %edi
        call    std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long)
        cmpq    main::arr+256, %rbx
        jne     .L2
        movl    std::cout, %edi
        call    std::basic_ostream >& std::endl >(std::basic_ostream >&)
        xorl    %eax, %eax
        popq    %rbx
        ret
        subq    $8, %rsp
        movl    std::__ioinit, %edi
        call    std::ios_base::Init::Init()
        movl    $__dso_handle, %edx
        movl    std::__ioinit, %esi
        movl    std::ios_base::Init::~Init(), %edi
        addq    $8, %rsp
        jmp     __cxa_atexit
    
    main::arr:
        .long   0
        .long   2
        .long   4
        .long   6
        .long   8
        .long   10
        .long   12
        .long   14
        .long   16
        .long   18
        .long   20
        .long   22
        .long   24
        .long   26
        .long   28
        .long   30
        .long   32
        .long   34
        .long   36
        .long   38
        .long   40
        .long   42
        .long   44
        .long   46
        .long   48
        .long   50
        .long   52
        .long   54
        .long   56
        .long   58
        .long   60
        .long   62
        .long   64
        .long   66
        .long   68
        .long   70
        .long   72
        .long   74
        .long   76
        .long   78
        .long   80
        .long   82
        .long   84
        .long   86
        .long   88
        .long   90
        .long   92
        .long   94
        .long   96
        .long   98
        .long   100
        .long   102
        .long   104
        .long   106
        .long   108
        .long   110
        .long   112
        .long   114
        .long   116
        .long   118
        .long   120
        .long   122
        .long   124
        .long   126
    

    i.e. none whatsoever.

提交回复
热议问题