2017-06-14 18 views
9

Tôi cần tạo một bộ n kiểu. Các loại n này là các kiểu giá trị của các loại n khác. Hãy xem xét đoạn mã này:Cách xác định một bộ giá trị của các loại giá trị từ gói tham số

#include <boost/hana.hpp> 

namespace hana = boost::hana; 

template<class... Types> 
class CartesianProduct 
{ 
public: 
    CartesianProduct(Types... args) : sets(args...) {} 

    hana::tuple<Types...> sets; 
    hana::tuple<Types...::value_type> combination; // does not work obviously... but wo can this be done? 
}; 

Việc áp dụng này được thiết kế như vậy: tôi vượt qua lớp này một gói tham số của container các loại có thể khác nhau. Lớp này đặt các vùng chứa này vào một bộ tóan sets. Lớp này cũng có một trường combination là một bộ gồm nhiều phần tử như các vùng chứa đã được chuyển đến lớp. Nhưng các loại phần tử là các loại giá trị của các vùng chứa khác nhau.

Lớp này sau đó được thiết kế để tạo ra sản phẩm Descartes lười biếng của các thùng chứa được chuyển đến nó và lưu trữ kết hợp hiện tại trong combination. Nhưng làm thế nào tôi có thể thực sự nhận được các loại giá trị của các container trong một thời trang variadic?

+0

Tất cả các loại có 'value_type' không? – StoryTeller

+0

Vâng, tôi làm điều này là điều kiện tiên quyết. –

+0

Nếu bạn viết lớp sản phẩm lười biếng này, sẽ thật tuyệt vời nếu bạn có thể đóng góp lại cho Hana. Tôi đang tìm kiếm để thêm các quan điểm lười biếng, và nó có thể là một ý tưởng tốt để thực hiện 'cartesian_product' lazily của chính nó. –

Trả lời

11

Nó có thể được thực hiện, tất nhiên. Bạn chỉ cần khai báo gói mở rộng một cách thích hợp.

hane::tuple<typename Types::value_type...> combination; 

Lưu ý việc sử dụng yêu cầu của trình chỉ định tên tệp. Quy tắc chung là xử lý tên gói dưới dạng một loại duy nhất. Các ràng buộc ngữ pháp/ngữ nghĩa giống nhau được áp dụng, vì chúng ta phải xác định rằng chúng ta truy cập một kiểu với toán tử phân giải phạm vi. Sau đó, chỉ cần tack mở rộng gói ở cuối.

Live Example

#include <vector> 
#include <map> 
#include <tuple> 

template<class... Types> 
class CartesianProduct 
{ 
public: 
    CartesianProduct(Types... args) : sets(args...) {} 

    std::tuple<Types...> sets; 
    std::tuple<typename Types::value_type...> combination; 
}; 


int main() { 
    std::vector<int> i; 
    std::map<int, std::vector<int>> m; 

    CartesianProduct<std::vector<int>, std::map<int, std::vector<int>>> 
     c(i, m); 

    return 0; 
} 
5

Mở rộng trên câu trả lời đúng người kể chuyện của (chấp nhận câu trả lời của mình xin vui lòng):

Tôi tìm thấy nó dễ dàng hơn để hình dung bản dịch kiểu như thế này bằng cách thực hiện chúng trong điều khoản của một meta- dịch chức năng, ví dụ:

#include <vector> 
#include <map> 
#include <tuple> 

namespace metafunction_impl 
{ 
    // meta function taking one type (T) and 'returning' one type. 
    // i.e. a unary metafunction 
    template<class T> struct get_value_type 
    { 
    using result = typename T::value_type; 
    }; 
} 

// provide clean interface to the metafunction 
template<class T> using GetValueType = typename metafunction_impl::get_value_type<T>::result; 

template<class... Types> 
class CartesianProduct 
{ 
public: 
    CartesianProduct(Types... args) : sets(args...) {} 

    std::tuple<Types...> sets; 

    // use my metafunction 
    std::tuple<GetValueType<Types>...> combination; 
}; 


int main() { 
    std::vector<int> i; 
    std::map<int, std::vector<int>> m; 

    CartesianProduct<std::vector<int>, std::map<int, std::vector<int>>> 
     c(i, m); 

    return 0; 
} 
+0

Đó là một hình ảnh rõ ràng về lý do tại sao người ta nên tưởng tượng các gói như một tên loại duy nhất. Tốt hơn là cách tiếp cận ngón tay cái của tôi. +1 – StoryTeller

Các vấn đề liên quan