gpt4 book ai didi

c++ - 使用模板元编程实现 std::all_of 的静态版本?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:24:14 28 4
gpt4 key购买 nike

前言。我试图更深入地了解 C++ 模板元编程,但似乎我被困住了……我正在编写一个库,我们将使用它来进行二进制数据 [反] 序列化。被解包的数据的预期结构在一定程度上是已知的,对我来说使用这些知识来(1)验证数据(2)跳过不相关的部分和(3)将数据直接解包到编译时已知的结构中似乎是合理的- 既避免不必要的复制,又使客户端代码看起来更简洁。

因此,例如,我想实现一个函数来解压数组(数组可以包含异构数据,如 JSON)。为简单起见,假设数组具有固定大小,并且没有嵌套。


实际问题 我想编写一个函数,它将接受一个包含序列化数据(或流 - 在我们的上下文中无关紧要)的输入缓冲区和一个 std::tuple,包含输出的左值(参数包是一个更糟糕的选择,因为我最终将不得不处理嵌套)。因此,我首先需要检查元组中的所有类型是否都适合解包器,如果不适合,则给出相关的错误消息。

所以代码是这样的:

template<typename T>
struct is_integral_lvalue : std::integral_constant<bool,
std::is_lvalue_reference<T>::value &&
std::is_integral<T>::value &&
(sizeof(T) == 4 || sizeof(T) == 8)>
{
};

/* ... */
template<typename TInputBuffer, typename... TDest>
static TRet unpack_int_tuple(TInputBuffer src_buf, std::tuple<TDest...> &&dest) noexcept(is_noexcept)
{
static_assert(typelist::all_are<is_integral_lvalue, TDest...>::value,
"All types in a tuple must be integral lvalue-references");
/* do unpacking */
}

条件 is_integral_constant 可以是任意的。这就是为什么希望 all_are 模板可以使用任何一元谓词。问题是:我应该在 typelist::all_are 中写什么(也许,我应该在上面的代码中修复什么才能写出这样的 all_are)?

一个有效的例子当然是理想的,但如果有帮助的话,我会很感激一般的想法/建议。

局限性 我的目标不仅仅是实现这个功能,而是了解它是如何工作的(像“只使用 boost::mpl”或“boost::hana”这样的解决方案是不合适的) .我们使用的不相关的东西越少越好。代码最好使用 C++11(我们还没有准备好在生产中使用 C++1y/GCC 4.9)。我也希望可以避免使用预处理器宏。

一些东西,我用谷歌搜索。 Boost.MPL,当然可以使用,但它很大,它使用缓慢的递归模板(而不是可变参数)并且很难理解“幕后”是什么。不幸的是,Boost::hana 基于多态 lambda,它没有进入 C++11。我看过这个https://github.com/Manu343726/Turbo库,但似乎需要对代码进行太多更改才能使用它(将几乎所有类型包装在它的适配器中)。它还使用惰性求值(在扩展模板时)之类的东西——这里不需要它,并且会使代码更难阅读。

本图书馆https://github.com/ldionne/mpl11 几乎是我需要的。问题再次出现在包装器上:and_ 是作为 foldr 元函数的特例实现的(展开以获得更好的编译时性能)。而且他们都使用元函数提升、惰性等等,这使得它真的很难理解(除了,也许,对于有经验的函数式语言程序员)。所以对我来说基本足够的是解释,如何跳过所有那些非常普遍和复杂的技术并编写相同的 and_ 模板,但以更简单的方式(用于更具体的用途)。

最佳答案

直到 C++17 和 fold expressions来吧,一个简单的实现 all_of是:

// base case; actually only used for empty pack
template<bool... values>
struct all_of : std::true_type {};

// if first is true, check the rest
template<bool... values>
struct all_of<true, values...> : all_of<values...> {};

// if first is false, the whole thing is false
template<bool... values>
struct all_of<false, values...> : std::false_type {};

在这种情况下用法变为

static_assert(all_of<is_integral_lvalue<TDest>::value...>::value,
"All types in a tuple must be integral lvalue-references");

如果你想保留原来的语法,使用别名很容易:

template<template <class> class T, class... U>
using all_are = all_of<T<U>::value...>;

此外,您的 is_integral_lvalue 中有一个错误- 引用类型不是整型。你的is_integral检查需要在 typename remove_reference<T>::type 上完成而不仅仅是 T .


编辑:这里是 all_of 的一个更简单的实现courtesy of @Columbo :

template<bool...> struct bool_pack;

template<bool...values> struct all_of
: std::is_same<bool_pack<values..., true>, bool_pack<true, values...>>{};

关于c++ - 使用模板元编程实现 std::all_of 的静态版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27221443/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com