如何使用可变参数模板实现折叠 [英] How to implement folding with variadic templates

查看:99
本文介绍了如何使用可变参数模板实现折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个几乎工作的解决方案。

I have an almost working solution. However, it fails to compile some simple cases, and I can't decipher the error message.

我目前的解决方案:

#define AUTO_RETURN( EXPR ) -> decltype( EXPR ) \
{ return EXPR; }

template< typename BinaryFunc, typename First, typename Second >
auto foldl( BinaryFunc&& func, First&& first, Second&& second )
AUTO_RETURN( func( std::forward<First>(first), std::forward<Second>(second) ) )

template<typename BinaryFunc, typename First, typename Second, typename... Rest >
auto foldl( BinaryFunc&& func, First&& first, Second&& second, Rest&&... rest )
AUTO_RETURN(
   foldl(
      std::forward<BinaryFunc>(func),
      func( std::forward<First>(first), std::forward<Second>(second) ),
      std::forward<Rest>(rest)... )
   )

预期

struct adder
{
   template< int LHS, int RHS >
   std::integral_constant<int,LHS+RHS>
   operator()( std::integral_constant<int,LHS>, std::integral_constant<int,RHS> )
   {
      return {};
   }
};

auto result = foldl( adder(),
      std::integral_constant<int,19>{},
      std::integral_constant<int,23>{}
   );

assert( result.value == 42 );

但此无法编译

foldl( adder(),
      std::integral_constant<int,1>{},
      std::integral_constant<int,2>{},
      std::integral_constant<int,3>{},
      std::integral_constant<int,4>{},
   );

奇怪的是,如果我删除所有 std :: forward and rvalue refs from the code it works fine

Oddly, if I remove all std::forward and rvalue refs from the code it works fine.

我是什么错误?

这是一个编译器错误吗?

What am I doing wrong?
Is this a compiler bug?

推荐答案

问题是<$ c $在变量 foldl 的返回类型中的 decltype 看不到变量 foldl 因为它还没有被完全声明,所以它不能递归到另一个实例化它自己。

The problem is that the decltype in the return type of the variadic foldl cannot see the variadic foldl, as it hasn't been fully declared yet, so it cannot recurse to another instantiation of itself.

你可以使用一个帮助 struct

template<typename BinaryFunc, typename... Args >
struct folder;

template<typename BinaryFunc, typename First, typename Second>
struct folder<BinaryFunc,First,Second>
{
    static auto foldl( BinaryFunc&& func, First&& first, Second&& second )
        AUTO_RETURN( func( std::forward<First>(first), std::forward<Second>(second) ) )
};

template<typename BinaryFunc, typename First, typename Second, typename... Rest >
struct folder<BinaryFunc,First,Second,Rest...>
{
    static auto foldl(BinaryFunc&& func, First&& first, Second&& second, Rest&&... rest )
        AUTO_RETURN(
            (folder<
            BinaryFunc,
             decltype(func( std::forward<First>(first), std::forward<Second>(second) )),Rest...>::
            foldl(
                std::forward<BinaryFunc>(func),
                func( std::forward<First>(first), std::forward<Second>(second) ),
                std::forward<Rest>(rest)... )
                ))
};

template< typename BinaryFunc, typename... Args >
auto foldl( BinaryFunc&& func, Args&& ... args )
AUTO_RETURN(
    (folder<BinaryFunc,Args...>::foldl(
      std::forward<BinaryFunc>(func),
      std::forward<Args>(args)... ))
   )

这篇关于如何使用可变参数模板实现折叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆