3

我正在用 C++ 编写一个程序,我应该将不同的函数嵌入到同一个for循环中。

例子:

for(i = 0; i < N_ITER; i++) {
    /* ... */
    function_A(); 
    /* ... */
}

for(i = 0; i < N_ITER; i++) {
    /* ... */
    function_B(); 
    /* ... */
}

出于性能考虑,我必须内联function_Afunction_B进入这个函数。我的第一个解决方案是使用 Functors 和函数模板,如下所示:

class function_A {
public:
    void operator()() {
        /* ... */   
    }
};

class function_B {
public:
    void operator()() {
        /* ... */
    }
};

template <class T>
class run {
public:
    void operator()() {
        /* ... */
        T func;
        for (i = 0; i < N_ITER; i++) {
            /* ... */
            func();
            /* ... */
        }
        /* ... */
    }
};

我可以调用如下函数:

run<function_A>()();
run<function_B>()();

但很快我发现代码中有太多重复的仿函数定义class xxx { public: void operator()() {...} };,看起来很尴尬。


所以我变成了一个使用 lambda 的解决方案:

auto function_A = []()
{
    /* ... */
};

auto function_B = []()
{
    /* ... */
};

template <class T>
class run {
public:
    T func;
    run(T func) : func(func) {}
    void operator()() {
        /* ... */
        for (i = 0; i < N_ITER; i++) {
            /* ... */
            func();
            /* ... */
        }
        /* ... */
    }
};

但这一次更难调用这些函数:

run<decltype(function_A)> funcA(function_A); funcA();
run<decltype(function_A)> funcB(function_A); funcB();

而且它不像以前的解决方案那样清晰。


是否有更优雅的方式在 C++ 中实现它?我错过了什么吗?任何建议,将不胜感激 !!!

4

2 回答 2

2

试试这个:

void run(std::function<void(void)> fn)
{
    for (int i = 0; i < N_ITER; i++)
        fn();
}

(...)

auto lambda1 = []()
    {
        std::cout << "Hello, world!\n";
    };

run(lambda1);

准备好这样run的函数/方法后,你也可以这样做:

class C
{
public:
    void operator()()
    {
        printf("Hello world from a functor!\n");
    }
};

(...)

C c;

run(c);

编辑:回应评论:

以前的解决方案没有内联。然而,这是:

template <typename T>
void run2(T fn)
{
    for (int i = 0; i < 10; i++)
        fn();
}

int main(int argc, char * argv[])
{
    getchar();

    auto lambda1 = []()
        {
            std::cout << "Hello, world!\n";
        };

    run2(lambda1);

    getchar();
}

拆卸:

        auto lambda1 = []()
            {
                std::cout << "Hello, world!\n";
            };

        run2(lambda1);
002E1280  mov         ecx,dword ptr ds:[2E3044h]  
002E1286  call        std::operator<<<std::char_traits<char> > (02E1730h)  
002E128B  dec         esi  
002E128C  jne         main+10h (02E1280h)

实际上,在 run2 的情况下使用仿函数的解决方案也被内联了,虽然有点长:

    C c;

    run2(c);
01031293  mov         esi,0Ah  
01031298  jmp         main+30h (010312A0h)  
0103129A  lea         ebx,[ebx]  
010312A0  mov         ecx,dword ptr ds:[1033044h]                          \
010312A6  mov         edx,10331ACh                                         |
010312AB  call        std::operator<<<std::char_traits<char> > (01031750h)  > loop 
010312B0  dec         esi                                                  |
010312B1  jne         main+30h (010312A0h)                                 /
于 2013-06-21T06:54:54.253 回答
1

关于您的关心

但很快我发现代码中有太多重复的仿函数定义 class xxx { public: void operator()() {...} };,看起来很尴尬。

你可能不应该写

class function_B {
public:
    void operator()() {
        /* ... */
    }
};

但是struct你保存一行语法混乱(public:)的版本,因为结构的成员默认是公共的:

struct function_B {
    void operator()() {
        /* ... */
    }
};

实际上,与简单的函数声明相比,IMO 的开销相当小。

当然 lambda 版本少了一点,再加上一个免费的模板函数,你也不需要decltype.

写。对于 lambda 解决方案,还必须考虑到您可以将整个定义struct放入头文件中,而您不能将 lambda对象的定义放入头文件中,如果该头文件用于多个翻译单元.

当然,所陈述的问题看起来很可能这些定义很可能会写入cpp文件中,因此 lambda 解决方案可能也可以正常工作。

于 2013-06-21T07:50:20.797 回答