c ++以任意数量的块的lambda函数可伸缩分组

Alb*_*ert 1 c++ variadic-functions template-specialization variadic-templates c++11

我必须执行几个lambda函数,但每个Nlambda都prologue()必须运行一个函数.lambdas的数量可以是任意大的,并且N在编译时是已知的.像这样的东西:

static void prologue( void )
{
    cout << "Prologue" << endl;
}

int main()
{
    run<3>( // N = 3
        [](){ cout << "Simple lambda func 1" << endl; },
        [](){ cout << "Simple lambda func 2" << endl; },
        [](){ cout << "Simple lambda func 3" << endl; },
        [](){ cout << "Simple lambda func 4" << endl; },
        [](){ cout << "Simple lambda func 5" << endl; },
        [](){ cout << "Simple lambda func 6" << endl; },
        [](){ cout << "Simple lambda func 7" << endl; }
    );
}
Run Code Online (Sandbox Code Playgroud)

输出:

Prologue
Simple lambda func 1
Simple lambda func 2
Simple lambda func 3
Prologue
Simple lambda func 4
Simple lambda func 5
Simple lambda func 6
Prologue
Simple lambda func 7
End
Run Code Online (Sandbox Code Playgroud)

必须妥善处理剩余物.

我已经达到了以下解决方案,但是你可以看到它不是很可扩展,因为我必须为每个解决方案编写一个处理程序N!

有可能做一些神奇的元编程来涵盖所有可能的N吗?我是否已经失去了焦点,并且有一种完全不同的方法来解决这个问题?必须在编译时解决所有问题.

#include <iostream>    
using namespace std;

static void prologue( void );

// Primary template
template< int N, typename... Args>
struct Impl;

// Specialitzation for last cases
template< int N, typename... Args >
struct Impl
{
    static void wrapper( Args... funcs )
    {
        Impl<N-1, Args...>::wrapper( funcs... );
    }
};

// Specilitzation for final case
template<int N>
struct Impl<N>
{
    static void wrapper( )
    {
        cout << "End" << endl;
    }
};

template< typename Arg1, typename... Args >
struct Impl<1, Arg1, Args...>
{
    static void wrapper( Arg1 func1, Args... funcs )
    {
        prologue();
        func1();

        Impl<1, Args...>::wrapper( funcs... );
    }
};

template< typename Arg1, typename Arg2, typename... Args >
struct Impl<2, Arg1, Arg2, Args...>
{
    static void wrapper( Arg1 func1, Arg2 func2, Args... funcs )
    {
        prologue();
        func1();
        func2();

        Impl<2, Args...>::wrapper( funcs... );
    }
};

template< typename Arg1, typename Arg2, typename Arg3, typename... Args >
struct Impl<3, Arg1, Arg2, Arg3, Args...>
{
    static void wrapper( Arg1 func1, Arg2 func2, Arg3 func3, Args... funcs )
    {
        prologue();
        func1();
        func2();
        func3();

        Impl<3, Args...>::wrapper( funcs... );
    }
};

// Static class implementation wrapper
template< int N, typename... Args >
static void run( Args... funcs )
{
    Impl<N, Args...>::wrapper( funcs... );
}
Run Code Online (Sandbox Code Playgroud)

编辑:发布了一个相关的问题.

max*_*x66 5

更简单的解决方案

template <std::size_t N, typename ... Ts>
void run (Ts const & ... fn)
 {
   using unused = int[];

   std::size_t  i { N-1U };

   (void)unused { 0, ( (++i % N ? 0 : (prologue(), 0)), (void)fn(), 0)... };
 }
Run Code Online (Sandbox Code Playgroud)

--EDIT--(void)在前面添加了fn()以避免Yakk在评论中解释的逗号劫持技巧(谢谢!).

  • `struct evil {int operator,(int)const {exit(-1); 返回42; }}; auto fn = [] {return evil {}; ```如果你将`fn()`的返回类型转换为`void`,它就不能劫持`,`.(这些令人讨厌的角落案例就是我喜欢在几个地方写一些"虐待"并在其他地方使用它的原因) (3认同)