如何从参数包中定义值类型的元组
How to define a tuple of value types from a parameter pack
我需要构建一个 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?
};
这个应用的目的是这样的:我传递这个class一个可能不同类型的容器的参数包。 class 将这些容器放入元组 sets
中。 class 也有一个字段 combination
,它是一个元组,包含与传递给 class 的容器一样多的元素。但是元素的类型是不同容器的值类型。
然后 class 用于懒惰地构建传递给它的容器的笛卡尔积,并将当前组合存储在 combination
中。但是我怎样才能真正以可变参数的方式获取容器的值类型呢?
当然可以。您只需要适当地声明包扩展。
hane::tuple<typename Types::value_type...> combination;
注意需要使用类型名称说明符。经验法则是将包名称视为单一类型。相同的 syntactic/semantic 约束适用,因为我们必须指定我们使用范围解析运算符访问类型。然后在最后添加扩展包。
#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;
}
扩展 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;
}
我需要构建一个 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?
};
这个应用的目的是这样的:我传递这个class一个可能不同类型的容器的参数包。 class 将这些容器放入元组 sets
中。 class 也有一个字段 combination
,它是一个元组,包含与传递给 class 的容器一样多的元素。但是元素的类型是不同容器的值类型。
然后 class 用于懒惰地构建传递给它的容器的笛卡尔积,并将当前组合存储在 combination
中。但是我怎样才能真正以可变参数的方式获取容器的值类型呢?
当然可以。您只需要适当地声明包扩展。
hane::tuple<typename Types::value_type...> combination;
注意需要使用类型名称说明符。经验法则是将包名称视为单一类型。相同的 syntactic/semantic 约束适用,因为我们必须指定我们使用范围解析运算符访问类型。然后在最后添加扩展包。
#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;
}
扩展 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;
}