C++11: Compile Time Calculation of Array

前端 未结 7 2107
长发绾君心
长发绾君心 2020-11-28 05:25

Suppose I have some constexpr function f:

constexpr int f(int x) { ... }

And I have some const int N known at compile time:

Either<

7条回答
  •  误落风尘
    2020-11-28 06:09

    There is a pure C++11 (no boost, no macros too) solution to this problem. Using the same trick as this answer we can build a sequence of numbers and unpack them to call f to construct a std::array:

    #include 
    #include 
    #include 
    #include 
    
    template
    struct seq { };
    
    template
    struct gens : gens { };
    
    template
    struct gens<0, S...> {
      typedef seq type;
    };
    
    constexpr int f(int n) {
      return n;
    }
    
    template 
    class array_thinger {
      typedef typename gens::type list;
    
      template 
      static constexpr std::array make_arr(seq) {
        return std::array{{f(S)...}};
      }
    public:
      static constexpr std::array arr = make_arr(list()); 
    };
    
    template 
    constexpr std::array array_thinger::arr;
    
    int main() {
      std::copy(begin(array_thinger<10>::arr), end(array_thinger<10>::arr), 
                std::ostream_iterator(std::cout, "\n"));
    }
    

    (Tested with g++ 4.7)

    You could skip std::array entirely with a bit more work, but I think in this instance it's cleaner and simpler to just use std::array.

    You can also do this recursively:

    #include 
    #include 
    #include 
    #include 
    #include 
    
    constexpr int f(int n) {
      return n;
    }
    
    template 
    constexpr
    typename std::enable_if>::type
    make() {
      return std::array{{Vals...}};
    }
    
    template 
    constexpr
    typename std::enable_if>::type 
    make() {
      return make();  
    }
    
    int main() {
      const auto arr = make<10>();
      std::copy(begin(arr), end(arr), std::ostream_iterator(std::cout, "\n"));
    }
    

    Which is arguably simpler.

提交回复
热议问题