在增强 hana 中过滤元组
Filtering a tuple in boost hana
template<class... Ts, class T>
constexpr auto contains(T&&){
auto types = hana::to<hana::tuple_tag>(hana::tuple_t<Ts...>);
return hana::bool_c<hana::find(types, hana::type_c<T>) != hana::nothing>;
}
auto ht = hana::make_tuple(1,2,3,'c');
auto ht1 = hana::filter(ht, [](auto t){
return contains<int,float,double>(t);
});
//prints 0
std::cout << hana::size(ht1) << std::endl;
我不确定我是否正确使用了增强hana,但contains
似乎有效。
std::cout << contains<int,float,double>(5) << std::endl; // 1
std::cout << contains<int,float,double>('c') << std::endl; // 0
std::cout << contains<int,float,double>(5.0f) << std::endl; // 1
为什么ht1
的大小为 0?
这里的问题实际上与Hana无关,它与推导通用引用的方式有关。只是为了澄清事情,hana::type_c<T> == hana::type_c<U>
正好等同于std::is_same<T, U>{}
.比较 hana::type
s 时,没有删除参考或 cv 限定符。您可以查看这些规则的各种文章(例如此或此(。
现在,让我浏览一下您的代码并修改一些带有注释的内容。第一
auto types = hana::to<hana::tuple_tag>(hana::tuple_t<Ts...>);
是多余的,因为您已经在使用 hana::tuple_t
创建hana::tuple
。因此,只有hana::tuple_t<T...>
就足够了。其次,有这样一句话:
return hana::bool_c<hana::find(types, hana::type_c<T>) != hana::nothing>;
与其检查hana::find(...) != hana::nothing
,不如使用 hana::contains
,它可以更好地表达您的意图,也可能更优化。一般来说,尤其是使用带有 Hana 的元编程库时,不要试图推理什么会更快。只要尽可能清楚地说明您的意图,并希望我在实施方面正确地完成我的工作:-(。因此,你最终会得到
return hana::bool_c<hana::contains(types, hana::type_c<T>)>;
现在,该hana::bool_c<...>
确实是多余的,因为hana::contains
已经返回了一个布尔integral_constant
。因此,以上相当于更简单的
return hana::contains(types, hana::type_c<T>);
最后,将所有位放在一起并简化,您可以得到
template<class... Ts, class T>
constexpr auto contains(T&&){
return hana::contains(hana::tuple_t<Ts...>, hana::type_c<T>);
}
我个人不喜欢将T&&
作为论据,而您实际上想要的只是该对象的类型。事实上,这迫使你实际上为contains
函数提供一个对象,这在某些情况下可能很笨拙(如果你周围没有对象怎么办?(。此外,将值与类型进行比较可能会令人困惑:
contains<int, char, double>(3.5) // wtf, 3.5 is not in [int, char, double]!
相反,如果这是我自己的代码,我会写以下内容:
template<class... Ts, class T>
constexpr auto contains(T type){
return hana::contains(hana::tuple_t<Ts...>, type);
}
// and then use it like
contains<int, char, double>(hana::type_c<double>)
但这是你函数界面的一部分,我想你比我更能判断你在界面方面的需求。
问题是T&&
,我认为它推断出类型为 T&
型,这意味着hana::type_c<T> != hana::type_c<T&>
解决方法是保留&&
,因为它们是不必要的。
template<class... Ts, class T>
constexpr auto contains(T){
auto types = hana::tuple_t<Ts...>;
return hana::find(types, hana::type_c<T>) != hana::nothing;
}
只是为了补充你的答案,你的ht1
用t
左值来调用contains
。下面演示了传递右值和右值情况下T&&
:
#include<boost/hana.hpp>
namespace hana = boost::hana;
template<class T>
void test1(T&&) {
static_assert(hana::type_c<T> == hana::type_c<int>, "");
}
int main() {
static_assert(hana::type_c<int> != hana::type_c<int&&>, "");
test1(5);
int x = 5;
test1(x); //fails
}
叮当输出:
main.cpp:7:3: error: static_assert failed ""
static_assert(hana::type_c<T> == hana::type_c<int>, "");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:14:3: note: in instantiation of function template specialization 'test1<int &>' requested here
test1(x); //fails
^
1 error generated.
- C++:TypeDef使用元组
- Pybind11:将元组列表从Python传递到C++
- 重载元组索引运算符-C++
- 在C++中,如何通过几种类型从元组中选择多个元素
- 将fold表达式与std::一起用于两个元组
- std::ranges::elements_view,用于自定义类似元组的数据
- 将元组的向量转换/构造为堆
- 专用于 std 元组的模板,而无需用户执行remove_cvref
- 将元组的向量构造成堆
- 元组由 Swig 生成的 Python 包装器返回,用于C++向量
- 将元组类型扩展为可变参数模板?
- 时间复杂度 当具有复合数据类型(如元组或对)时?
- 类内部和外部静态 constexpr 元组之间的差异
- 可变参数模板与使用元组在参数中添加不同的数据对
- 访问和打印元组中的数据,并使用 C++14 使用模板函数显示数据
- boost::包含提升单元的元组的哈希值
- 我正在寻找一种优雅的方式来从元组向量创建tuple_element向量
- 如何从元组C 过滤重复类型
- 在增强 hana 中过滤元组
- 如何根据表达式在Boost.Hana中是否有效来过滤类型元组