2017-08-29 29 views
7

Tôi đã đọc this câu hỏi về SO.Thời gian biên dịch khởi tạo mảng - Trình tự Constexpr

Bản thân câu hỏi không thú vị lắm, nhưng tôi đã tự hỏi liệu nó có tồn tại không và cách triển khai giải pháp thời gian biên dịch.

liên quan đến các chuỗi đầu tiên:

Tất cả số ngoại trừ những có thể được chia cho 3.

Chuỗi nên một cái gì đó như:

[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, ...] 

By cảm ứng , Tôi đã tìm thấy công thức toán học cho chuỗi đó:

f(0) = 0; 
f(x > 0) = floor[(3x - 1)/2]; 

Vì vậy, tôi đã thực hiện một chức năng C++ constexpr mà tạo ra thứ i số trong dãy:

#include <type_traits> 

template <typename T = std::size_t> 
constexpr T generate_ith_number(const std::size_t index) { 
    static_assert(std::is_integral<T>::value, "T must to be an integral type"); 

    if (index == 0) return 0; 
    return (3 * index - 1)/2; 
} 

Bây giờ tôi muốn tạo ra một "thời gian biên dịch mảng/chuỗi" lưu trữ số thứ tự đầu tiên của chuỗi.

Cấu trúc nên một cái gì đó như:

template <typename T, T... values> 
struct sequence {}; 

template <typename T, std::size_t SIZE> 
struct generate_sequence {}; // TODO: implement 

câu hỏi (nhiều hơn một, nhưng có liên quan trong đó):

1) Làm thế nào để thực hiện điều đó loại integer_sequence?

2) Có thể xây dựng std::array từ số integer_sequence lúc biên dịch không?

Trả lời

12

1) Cách triển khai loại integer_sequence?

template <std::size_t... Is> 
constexpr auto make_sequence_impl(std::index_sequence<Is...>) 
{ 
    return std::index_sequence<generate_ith_number(Is)...>{}; 
} 

template <std::size_t N> 
constexpr auto make_sequence() 
{ 
    return make_sequence_impl(std::make_index_sequence<N>{}); 
} 

2) Có thể xây dựng một std::array từ integer_sequence rằng tại thời điểm biên dịch?

template <std::size_t... Is> 
constexpr auto make_array_from_sequence_impl(std::index_sequence<Is...>) 
{ 
    return std::array<std::size_t, sizeof...(Is)>{Is...}; 
} 

template <typename Seq> 
constexpr auto make_array_from_sequence(Seq) 
{ 
    return make_array_from_sequence_impl(Seq{}); 
} 

Cách sử dụng:

int main() 
{ 
    constexpr auto arr = make_array_from_sequence(make_sequence<6>()); 
    static_assert(arr[0] == 0); 
    static_assert(arr[1] == 1); 
    static_assert(arr[2] == 2); 
    static_assert(arr[3] == 4); 
    static_assert(arr[4] == 5); 
    static_assert(arr[5] == 7); 
} 

live example on wandbox.org

+1

Với khấu trừ hàm tạo C++ 17, 'std :: array {Is ...};' có thể được đơn giản hóa thành 'std :: array {Is ... }; '. – metal

1

Nó là khá dễ dàng để tạo ra mảng sử dụng mã khá đơn giản trong C++ gần đây:

template<typename T, T N> 
constexpr auto make_constexpr_array(std::integral_constant<T, N>) 
{ 
    std::array<int,N> result = {}; 
    for (int i = 0; i < N; ++i) 
     result[i] = (3*i - 1)/2; 
    return result; 
} 

int main() 
{ 
    constexpr auto arr = make_constexpr_array(std::integral_constant<int, 6>{}); 
    static_assert(arr[0] == 0); 
    static_assert(arr[1] == 1); 
    static_assert(arr[2] == 2); 
    static_assert(arr[3] == 4); 
    static_assert(arr[4] == 5); 
    static_assert(arr[5] == 7); 
} 
Các vấn đề liên quan