如何使用可变参数模板实现折叠 [英] How to implement folding with variadic templates
本文介绍了如何使用可变参数模板实现折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个几乎工作的解决方案。
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
的返回类型中的 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屋!
查看全文