How to implement folding with variadic templates

后端 未结 2 1749
-上瘾入骨i
-上瘾入骨i 2020-12-16 00:28

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

My current solution:

#de         


        
相关标签:
2条回答
  • 2020-12-16 01:08

    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.

    You can do it with a helper 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)... ))
       )
    
    0 讨论(0)
  • 2020-12-16 01:23

    Thank you for a great question that caused me to look into a few new areas in C++11.

    Anthony W. was faster with a solution; but I still want to share mine, which also uses a helper struct (and it's admittedly more verbose). First, let me share a link to a similar question trailing return type using decltype with a variadic template function; the answers there are based on the same idea of a helper struct, so their authors deserve credit.

    The code below is checked with ideone. Note that it does not use AUTO_RETURN anymore, as the helper struct now takes care of the type.

    template< typename BinaryFunc, typename First, typename... Types >
    struct helper;
    
    template< typename BinaryFunc, typename First>
    struct helper<BinaryFunc, First> {
        typedef decltype(std::declval<First>()) type;
    };
    
    template< typename BinaryFunc, typename First, typename Second >
    struct helper<BinaryFunc, First, Second> {
        typedef decltype(
            std::declval<BinaryFunc>()( std::declval<First>(), std::declval<Second>() )
        ) type;
    };
    
    template< typename BinaryFunc, typename First, typename Second, typename... Rest >
    struct helper<BinaryFunc, First, Second, Rest...>  {
        typedef typename helper< BinaryFunc,
                                 typename helper<BinaryFunc, First, Second>::type,
                                 Rest...
                               >::type
                         type;
    };
    
    template< typename BinaryFunc, typename First, typename Second >
    typename helper<BinaryFunc, First, Second>::type
    foldl( BinaryFunc&& func, First&& first, Second&& second ) {
        return func( std::forward<First>(first), std::forward<Second>(second) );
    }
    
    template< typename BinaryFunc, typename First, typename Second, typename... Rest >
    typename helper<BinaryFunc, First, Second, Rest...>::type
    foldl( BinaryFunc&& func, First&& first, Second&& second, Rest&&... rest ) {
       return foldl(
          std::forward<BinaryFunc>(func),
          func( std::forward<First>(first), std::forward<Second>(second) ),
          std::forward<Rest>(rest)...
       );
    }
    
    0 讨论(0)
提交回复
热议问题