10

我需要构建一个 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. 但是我怎样才能真正以可变的方式获得容器的值类型呢?

4

2 回答 2

13

当然可以。您只需要适当地声明包扩展。

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;
}
于 2017-06-14T06:15:55.123 回答
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;
}
于 2017-06-14T06:48:43.537 回答