C++ 使用模板元编程实现std::all_的静态版本?

C++ 使用模板元编程实现std::all_的静态版本?,c++,c++11,template-meta-programming,fold,C++,C++11,Template Meta Programming,Fold,前言。我试图对C++模板元编程有更深的理解,看来我陷入了困境…我正在编写一个库,我们将使用它进行二进制数据[反]序列化。解包数据的预期结构在一定程度上是已知的,我使用这些知识(1)验证数据(2)跳过不相关的部分,(3)将数据直接解包到编译时已知的结构中似乎是合理的——这两种方法都是为了避免不必要的复制,并使客户机代码看起来更干净 例如,我想实现一个函数,它将解压一个数组(数组可以包含异构数据,如JSON中的数据)。为了简单起见,假设数组具有固定大小,并且没有嵌套 实际问题我想写一个函数,它将接

前言。我试图对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 */
}
模板
结构是整数值:std::整数值
{
};
/* ... */
模板
静态TRet unpack_int_tuple(TInputBuffer src_buf,std::tuple&dest)noexcept(is_noexcept)
{
静态_断言(typelist::all_are::value,
“元组中的所有类型都必须是整数左值引用”);
/*开箱*/
}
条件
是积分常数
可以是任意的。这就是为什么
all\u是
template可以使用任何一元谓词的原因。问题是:我应该在
typelist::all_are
中写什么(也许,我应该在上面的代码中修改什么,以便能够写这样的
all_are

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

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

一些东西,我在谷歌上搜索过。当然可以使用Boost.MPL,但它很大,它使用缓慢的递归模板(而不是变量),很难理解“幕后”是什么。不幸的是,hana是基于多态lambdas的,它没有进入C++11。我见过这个库,但它似乎需要对代码进行太多的更改才能使用它(在它的适配器中封装几乎所有类型)。它还使用了诸如惰性评估(在扩展模板时)之类的东西——这里不需要它,而且会使代码更难阅读

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

在C++17出现之前,
所有
的简单实现是:

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

建议使用非MPL版本的
,现在改名为
conjunction

很久以前,实现是在libstdc++(如
std::u和
中的
)中实现的


是我的更简单的实现(不太明确的专门化)。

我不会把它称为引用类型,如果你在模板中使用
t&&
,你基本上允许任何东西进入,这就是Scott Meyers所称的通用引用。@user2485710 inb4该术语已被弃用。您现在要查找的是“.”user2485710错误在于同时检查
std::is_lvalue\u reference::value
std::is_integral::value
。“ReMyabelOP没有指定他想要使用的C++版本,他偏爱C++ 11,我们已经在谈论C++ 17?@ MikHaelMaltSev。元组被当作一个R值引用,而不是一个Fravud/EngultRealth.如果您想要转发引用,则需要将整个类型作为模板参数,然后分别提取包含的类型。很高兴看到有人考虑使用我的库,即使它最终被拒绝。非常感谢:)
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...>;
template<bool...> struct bool_pack;

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