2013-09-25 34 views
11

tôi đang tìm cách để tạo ra một bảng tra cứu tọa độ, một cái gì đó như:Lookup bảng với constexpr

int a[n][2] = {{0,1},{2,3}, ... } 

Đối với một trao n, được tạo ra tại thời gian biên dịch. Tôi bắt đầu nhìn vào constexpr, nhưng có vẻ như một hàm trả về một constexpr std::vector<std::array <int, 2> > không phải là một lựa chọn, như tôi nhận được:

invalid return type 'std::vector<std::array<int, 2ul> >' of constexpr function 

Làm thế nào có thể tạo ra như một mảng thời gian biên dịch?

+1

'std :: vector' không phải là một loại đen và do đó không thể được được sử dụng trong C++ 11 'constexpr'. Kiểu 'mảng' của C++ 11 thiếu các tham số' constexpr' và do đó cũng sử dụng hạn chế trong các hàm 'constexpr'. Nếu bạn không có một số hỗ trợ lib/biên dịch C++ 1y, tôi khuyên bạn nên sử dụng một loại mảng tùy chỉnh thay thế. – dyp

+0

@DyP - bạn có thể hiển thị ví dụ không? – nbubis

+0

Sẽ hữu ích hơn nếu bạn thêm một số chi tiết về những gì bạn muốn làm;) – dyp

Trả lời

15

Tôi sẽ đổ mã trước, thêm tham chiếu và nhận xét khi cần/thích hợp sau này. Chỉ cần để lại một bình luận nếu kết quả là phần nào gần với những gì bạn đang tìm kiếm.

Bí quyết mở rộng gói (yêu cầu ở đây để áp dụng trình tạo), Xeo, từ this answer, được sửa đổi để sử dụng std::size_t thay vì unsigned.

#include <cstddef> 

// by Xeo, from https://stackoverflow.com/a/13294458/420683 
template<std::size_t... Is> struct seq{}; 
template<std::size_t N, std::size_t... Is> 
struct gen_seq : gen_seq<N-1, N-1, Is...>{}; 
template<std::size_t... Is> 
struct gen_seq<0, Is...> : seq<Is...>{}; 

Generator chức năng:

#include <array> 

template<class Generator, std::size_t... Is> 
constexpr auto generate_array_helper(Generator g, seq<Is...>) 
-> std::array<decltype(g(std::size_t{}, sizeof...(Is))), sizeof...(Is)> 
{ 
    return {{g(Is, sizeof...(Is))...}}; 
} 

template<std::size_t tcount, class Generator> 
constexpr auto generate_array(Generator g) 
-> decltype(generate_array_helper(g, gen_seq<tcount>{})) 
{ 
    return generate_array_helper(g, gen_seq<tcount>{}); 
} 

Cách sử dụng Ví dụ:

// some literal type 
struct point 
{ 
    float x; 
    float y; 
}; 
// output support for `std::ostream` 
#include <iostream> 
std::ostream& operator<<(std::ostream& o, point const& p) 
{ return o << p.x << ", " << p.y; } 

// a user-defined generator 
constexpr point my_generator(std::size_t curr, std::size_t total) 
{ 
    return {curr*40.0f/(total-1), curr*20.0f/(total-1)}; 
} 

int main() 
{ 
    constexpr auto first_array = generate_array<5>(my_generator); 
    constexpr auto second_array = generate_array<10>(my_generator); 

    std::cout << "first array: \n"; 
    for(auto p : first_array) 
    { 
     std::cout << p << '\n'; 
    } 
    std::cout << "========================\n"; 

    std::cout << "second array: \n"; 
    for(auto p : second_array) 
    { 
     std::cout << p << '\n'; 
    } 
} 
+1

Wow - Thats rất nhiều mã! Đó có thực sự là cách ngắn nhất để làm điều này không? – nbubis

+0

@nbubis Đây là một giải pháp rất chung chung. Nếu bạn thu hẹp/chỉ định chính xác hơn những gì bạn muốn, có thể có một giải pháp tiết kiệm hơn. – dyp

+0

Tôi nghĩ rằng ví dụ sử dụng của anh ấy là chính xác những gì tôi đang tìm kiếm, nhưng chắc chắn là rất nhiều mã phụ :) – nbubis

-1

gì về việc sử dụng GNU gperf hoặc một số tiện ích hệ mã khác?

+1

Xin chào. Bạn có thể sử dụng gperf để khởi tạo một vector tại thời gian biên dịch không? Và nếu như thế thì sao? –

14

Với C++ 14, bạn không cần quá nhiều mẫu ma thuật. Dưới đây là một ví dụ về cách để có một bảng tra cứu cho f(x) = x^3 với người đầu tiên phối hợp là giá trị x và thứ hai phối hợp là giá trị f(x):

#include <iostream> 

template<int N> 
struct Table 
{ 
    constexpr Table() : values() 
    { 
     for (auto i = 0; i < N; ++i) 
     { 
      values[i][0] = i; 
      values[i][1] = i * i * i; 
     } 
    } 
    int values[N][2]; 
}; 

int main() { 
    constexpr auto a = Table<1000>(); 
    for (auto x : a.values) 
     std::cout << "f(" << x[0] << ") = " << x[1] << '\n'; 
} 
+0

Thực sự tốt đẹp !! Rất nhiều C++ 1x để tìm hiểu .. – nbubis

+0

Ý nghĩa của: ': values ​​()' trong 'constexpr Table(): values ​​()' là gì? Nó không khởi tạo hay gì đó? – Jonas

+0

& Jonas Có, nó không khởi tạo là cần thiết vì C++ cần phải có một giá trị biên dịch-const. Nó sẽ được thiết lập trong constructor sau nhưng điều này khó theo dõi bởi trình biên dịch – IceFire