c++ - Boost Hana 实现自定义序列
问题描述
我面临一种情况,我通常会通过继承来创建自定义类boost::hana::tuple
。例如,通过使用以下代码,
template<typename ... args>
struct my_nonworking_custom_tuple_t : public boost::hana::tuple<args ...> //not working!!!
{
using base = boost::hana::tuple<args ...>;
//... all other stuff
auto my_getter() const { return base::operator[](1_c); }
};
然而,这并不像boost::hana::tuple
实现为final
.
因此,我似乎被迫使用构图,
template<typename ... args>
struct my_custom_tuple_t
{
//... all other stuff
boost::hana::tuple<args ...> tup;
auto my_getter() const { return tup[1_c]; }
};
但是,一旦我这样做,生成的类就不再对 Hana 概念“序列”进行建模,因此我无法应用所有方便的 Hana 方法。
我需要做什么才能变成my_custom_tuple_t
Hana 序列?
解决方案
通常你不需要这样做,但这里有一个指南,用于实现你自己Sequence
的以及满足 Boost.Hana 中其他概念的要求。(后者应该对不提供自己的元组实现的最终用户有用。)
从文档中的最小完整定义(MCD)开始hana::Sequence
在那里你会看到,要实现Sequence
你的数据类型必须实现make
函数以及满足和的Iterable
要求Foldable
。
因此,您必须为其提供实现的 Hana 函数的完整列表如下:
at
drop_front
is_empty
make
unpack
此外,请注意 Boost.Hana 有两种元组类型tuple
和basic_tuple
. basic_tuple
重量更轻,因此您应该将其用于存储。
要使用 Boost.Hana 的标签调度,您可以实现hana::tag_of
或简单地提供hana_tag
类型别名作为类的成员。
#include <boost/hana.hpp>
#include <utility>
namespace mine {
struct my_custom_tuple_tag { };
template<typename ... args>
struct my_custom_tuple_t {
using hana_tag = my_custom_tuple_tag;
//... all other stuff
boost::hana::basic_tuple<args ...> tup;
auto my_getter() const {
return boost::hana::at_c<1>(tup);
}
};
}
namespace boost::hana {
// Iterable
template <>
struct at_impl<mine::my_custom_tuple_tag> {
template <typename Xs, typename N>
static constexpr decltype(auto) apply(Xs&& xs, N const&) {
return at_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup, N{});
}
};
template <>
struct drop_front_impl<mine::my_custom_tuple_tag> {
template <typename Xs, typename N>
static constexpr auto apply(Xs&& xs, N const&) {
return drop_front_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup);
}
};
template <>
struct is_empty_impl<mine::my_custom_tuple_tag> {
template <typename Xs>
static constexpr auto apply(Xs const& xs) {
return is_empty_impl<basic_tuple_tag>(xs).tup;
}
};
// Foldable
template <>
struct unpack_impl<mine::my_custom_tuple_tag> {
template <typename Xs, typename F>
static constexpr auto apply(Xs&& xs, F&& f) {
return unpack_impl<basic_tuple_tag>(std::forward<Xs>(xs).tup,
std::forward<F>(f));
}
};
// Sequence
template <>
struct make_impl<mine::my_custom_tuple_tag> {
template <typename ...Args>
static constexpr auto apply(Args&& ...args) {
return make_impl<basic_tuple_tag>(std::forward<Args>(args)...);
}
};
template <>
struct Sequence<mine::my_custom_tuple_tag> : std::true_type { };
}
值得注意的是,用于检查的模板Sequence
只是一个可选的模板专业化。我确信这只是节省编译时计算的捷径,因为其他概念依赖于检查其所需函数的非默认实现。
推荐阅读
- javascript - 如何在div中查找元素的值?
- javascript - 为什么这个级联下拉列表中的第三个和第四个框没有 javascript 没有填充?
- websphere - Websphere 8.5 重新启动会破坏 classLoader 代码
- validation - 在 symfony 3 中没有调用验证器时要检查什么?
- python - 如何存储和使用数学运算符作为 python 变量
- java - 如何在 Spring 框架中修复 UnsatisfiedDependencyException
- c# - C# 泛型 - 有人可以解释这个签名吗
- graph - 查找长度 = 4 的路径,从有向图的邻接矩阵开始,只考虑不同的边?
- android - 首先从firebase实时数据库中检索新项目
- javascript - 如何将预览图像的位图发送到控制器?