Why is non-const std::array::operator[] not constexpr?

后端 未结 4 517
终归单人心
终归单人心 2020-12-14 16:03

I\'m trying to fill a 2D array on compile time with a given function. Here is my code:

template
struct Table
{
  int data[H][W];
  //std:         


        
4条回答
  •  感情败类
    2020-12-14 16:20

    This question intrigued me so much that I decided to figure out a solution that would allow the array to be initialised at compile time with a function that took x and y as parameters.

    Presumably this could be adapted for any number of dimensions.

    #include 
    #include 
    
    
    // function object that turns x and y into some output value. this is the primary predicate
    struct init_cell_xy
    {
        constexpr init_cell_xy() = default;
    
        constexpr int operator()(int x, int y) const
        {
            return (1 + x) * (1 + y);
        }
    };
    
    // function object that applies y to a given x
    template
    struct init_cell_for_x
    {
        constexpr init_cell_for_x() = default;
    
        constexpr int operator()(int y) const
        {
            return _xy(X, y);
        }
    
    private:
        init_cell_xy _xy;
    };
    
    // an array of dimension 1, initialised at compile time
    template
    struct array1
    {
        template
        constexpr array1(F&& f, std::integer_sequence)
        : _values { f(Is)... }
        {}
    
        template
        constexpr array1(F&& f = init_cell_for_x<>())
        : array1(std::forward(f), std::make_integer_sequence())
        {}
    
        constexpr auto begin() const { return std::begin(_values); }
        constexpr auto end() const { return std::end(_values); }
        constexpr auto& operator[](size_t i) const {
            return _values[i];
        }
    
    private:
        int _values[Extent];
    
        friend std::ostream& operator<<(std::ostream& os, const array1& s)
        {
            os << "[";
            auto sep = " ";
            for (const auto& i : s) {
                os << sep << i;
                sep = ", ";
            }
            return os << " ]";
        }
    };
    
    // an array of dimension 2 - initialised at compile time
    template
    struct array2
    {
        template
        constexpr array2(std::integer_sequence)
        : _xs { array1(init_cell_for_x())... }
        {}
    
        constexpr array2()
        : array2(std::make_integer_sequence())
        {}
    
        constexpr auto begin() const { return std::begin(_xs); }
        constexpr auto end() const { return std::end(_xs); }
        constexpr auto& operator[](size_t i) const {
            return _xs[i];
        }
    
    private:
        array1 _xs[XExtent];
    
        friend std::ostream& operator<<(std::ostream& os, const array2& s)
        {
            os << "[";
            auto sep = " ";
            for (const auto& i : s) {
                os << sep << i;
                sep = ",\n  ";
            }
            return os << " ]";
        }
    
    };
    
    
    
    
    auto main() -> int
    {
        using namespace std;
    
        constexpr array2<6,6> a;
    
        cout << a << endl;
        return 0;
    }
    

提交回复
热议问题