【问题标题】:How to define a tuple of value types from a parameter pack如何从参数包中定义值类型的元组
【发布时间】:2017-11-16 03:09:57
【问题描述】:

我需要构建一个 n 类型的元组。这 n 个类型是 n 个其他类型的值类型。考虑一下这个 sn-p:

#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 中。但是我怎样才能真正以可变的方式获取容器的值类型呢?

【问题讨论】:

  • 所有类型都有value_type吗?
  • 好吧,我把这个作为前提条件。
  • 如果你写了这个懒惰的笛卡尔积类,如果你能把它贡献给 Hana 那就太棒了。我正在寻找添加惰性视图,最好自己实现 cartesian_product 惰性。

标签: c++ tuples variadic-templates boost-hana


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    扩展 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;
    }
    

    【讨论】:

    • 这是一个可靠的可视化说明为什么人们应该把包想象成一个单一的类型名称。比我的经验法则更好。 +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-03
    • 2012-11-25
    • 1970-01-01
    相关资源
    最近更新 更多