2017-06-14 60 views
9

我需要构建n个类型的元组。这n个类型是n个其他类型的值类型。考虑这个片断:如何从参数包中定义值类型的元组

#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? 
}; 

的这个应用程序的目的是,像这样:我通过这个类可能是不同类型的容器的参数包。这个类将这些容器放入一个元组sets。该类还有一个字段combination,它是容器传递给该类的许多元素的元组。但是元素的类型是不同容器的值类型。

然后,该类将懒散地构建传递给它的容器的笛卡尔积,并将当前组合存储在combination中。但是我怎样才能真正以可变的方式获得容器的值类型?

+0

是否所有类型都有'value_type'? – StoryTeller

+0

嗯,我把这作为一个先决条件。 –

+0

如果你确实写了这个懒惰的笛卡尔产品类,那么如果你能将它贡献给Hana,那将是非常棒的。我期待添加懒惰的视图,并且它本身可以懒惰地实现'cartesian_product'是一个好主意。 –

回答

11

当然可以做到。你只需要适当地声明包扩展。

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

注意需要使用typename说明符。经验法则是将包名称视为单一类型。应用相同的语法/语义约束,因为我们必须指定我们使用范围解析运算符访问类型。然后在最后加上包装扩展。

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

上的说书人的正确答案扩展(接受他的答案,请):

我觉得它更容易通过翻译荟萃的条款执行这些可视化类型的翻译是这样功能,例如:

#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

这就是为什么人们应该将这个包想象为一个单一类型名称的可视化。比我的经验法则更好。 +1 – StoryTeller

相关问题