如何从参数包中定义值类型的元组

lo *_*cre 9 c++ tuples variadic-templates boost-hana

我需要构建一个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?
};
Run Code Online (Sandbox Code Playgroud)

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

然后,该类旨在懒惰地构建传递给它的容器的笛卡尔积,并将当前组合存储在其中combination.但是,我怎样才能以可变方式实际获取容器的值类型?

Sto*_*ica 12

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

hane::tuple<typename Types::value_type...> combination; 
Run Code Online (Sandbox Code Playgroud)

请注意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;
}
Run Code Online (Sandbox Code Playgroud)


Ric*_*ges 5

扩展StoryTeller的正确答案(请接受他的回答):

通过在翻译元函数方面实现它们,我发现通过这种方式可视化类型翻译更容易,例如:

#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;
}
Run Code Online (Sandbox Code Playgroud)