2012-02-16 12 views
7

Tôi muốn xây dựng boost::variant s chứa giá trị được tạo mặc định, được chỉ định bằng chỉ mục loại - mà không cần viết câu lệnh chuyển đổi của riêng tôi qua chỉ mục loại.Xây dựng một biến thể tăng có chứa giá trị của loại thứ n trong chỉ mục loại biến thể?

Tôi tìm số này phải là có thể, bằng cách nào đó, với MPL?

Để làm rõ, chỉ mục không phải là biểu thức hằng số biên dịch.

Trường hợp sử dụng là tôi cần phải tạo một biến thể mà sau này sẽ được thay thế bằng một biến chứa giá trị chính xác, nhưng tại thời điểm này tôi chỉ biết chỉ mục loại. Hãy nghĩ về nó như một vấn đề deserialisation lười biếng.

+0

Vì bạn đề cập đến MPL, tôi nghĩ rằng 'N' (chỉ mục kiểu) được biết tại thời gian biên dịch, tuy nhiên, việc deserialization lười biếng cho thấy nó chỉ có thể có sẵn khi chạy -> đó là nó? –

+0

@MatthieuM. Điều này sẽ là không thể với sau này. Tôi hy vọng cho lần đầu tiên, nếu không câu trả lời của tôi là vô giá trị là tốt. – pmr

+0

@MatthieuM. Ah, điểm tốt: nó chỉ có sẵn trong thời gian chạy. – James

Trả lời

11

Bạn cần sử dụng mã số variant::types. Điều này cung cấp cho bạn một chuỗi tương thích MPL mà sau đó chúng tôi có thể sử dụng với mpl::at và một mẫu để thực hiện đặt giá thầu của chúng tôi. Đây hiện các trick:

#include <string> 
#include <boost/variant.hpp> 
#include <boost/mpl/at.hpp> 
#include <boost/mpl/int.hpp> 

template<typename U, typename V> 
void construct_in(V& v) { 
    v = U(); 
    // modern 
    // v = U{}; 
} 

int main() 
{ 
    typedef boost::variant<int, std::string> variant; 
    typedef boost::mpl::at<variant::types, boost::mpl::int_<1>>::type pos; 
    variant v; 
    // use type deduction 
    construct_in<pos>(v); 
    // does not throw, does work 
    std::string& s =boost::get<std::string>(v); 
    return 0; 
} 

Ở đây sẽ là thời gian chạy-variant:

#include <string> 
#include <vector> 
#include <functional> 

#include <boost/variant.hpp> 
#include <boost/mpl/at.hpp> 
#include <boost/mpl/int.hpp> 
#include <boost/mpl/for_each.hpp> 

typedef boost::variant<int, std::string> variant; 
typedef variant::types types; 
typedef std::vector< std::function<void(variant&)> > fvec; 

template<typename U, typename V> 
void construct_in(V& v) { 
    v = U{}; 
} 

struct build_and_add { 
    fvec* funcs; 
    template<typename T> 
    void operator()(T) { 
    funcs->push_back(&construct_in<T, variant>); 
    } 
}; 


int main() 
{ 

    variant v; 
    std::vector< std::function<void(variant&)> > funcs; 

    // cannot use a lambda, would need to be polymorphic 
    build_and_add f = {&funcs}; 
    boost::mpl::for_each<types>(f); 

    // this is runtime! 
    int i = 1; 

    funcs[i](v); 
    // does not throw, does work 
    std::string& s =boost::get<std::string>(v); 
    return 0; 
} 

Đó là một chút phức tạp và sẽ cần một số tinh chỉnh với variadic lập luận là thực sự chung, nhưng nó làm những gì bạn muốn . Một người khác cần phải tìm hiểu xem điều này có dẫn đến sự bùng nổ mã quan trọng hay không.

+0

Xin lỗi vì làm rõ về loại chỉ mục là thời gian chạy, nhưng tôi không nghĩ câu trả lời này là vô dụng - có thể mở rộng điều này để chuyển đổi giữa N chỉ số liên tục tại thời gian chạy, trong đó chỉ N được cố định tại biên dịch thời gian (và thậm chí có thể được trích xuất từ ​​các biến thể, có lẽ?) – James

+0

@Autopulated Không thực sự, nhưng một số ma thuật đen có thể giúp đỡ. Hãy nghĩ về mẫu chúng tôi sử dụng để xây dựng. Chúng ta có thể tạo tất cả các mẫu đó tại thời gian biên dịch và lưu trữ chúng dưới dạng các đối tượng 'std :: function' trong một vectơ và sử dụng vector này trong thời gian chạy để tra cứu những gì chúng ta muốn xây dựng. Tôi sẽ cố gắng để ném một cái gì đó với nhau, nhưng tôi không biết làm thế nào tốt mà sẽ được trong điều khoản của mã blow-up vv – pmr

+0

@pmr: phản ứng đầu gối-jerk của tôi là sử dụng đệ quy, nhưng một vector (hoặc mảng kể từ N là hằng số) của con trỏ tới các hàm có vẻ như đảm bảo hiệu suất tốt hơn nhiều (không phụ thuộc vào một đệ quy đuôi cuối cùng). Bạn có thể cần đệ quy cho việc khởi tạo của vectơ vẫn còn, nhưng đó là một điều duy nhất. –