3

I am writing a program in C++ that I should embed different functions into a same for loop.

Examples:

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

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

For performance consideration I must inline function_A and function_B into this function. My first solution is using Functors and function templates as follows:

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();
            /* ... */
        }
        /* ... */
    }
};

And I can call the functions like:

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

But soon I found that there's too much duplicated functor definations class xxx { public: void operator()() {...} }; in code and it looks awkward.


So I turned into a solution using 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();
            /* ... */
        }
        /* ... */
    }
};

But this time its harder to call these functions:

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

And it is not as clear as the previous solution.


It there a more elegant way to implement it in C++? Am I missing something? Any suggestions would be appreciated !!!

Naruil
  • 2,300
  • 11
  • 15

2 Answers2

2

Try this:

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);

After preparing such run function / method, you'll be able to do this as well:

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

(...)

C c;

run(c);

Edit: In response to comments:

The previous solution was not inlined. However, this was:

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();
}

Disassembly:

        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)

Actually, the solution with functor in case of run2 was also inlined, though a little bit longer:

    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)                                 /
Spook
  • 25,318
  • 18
  • 90
  • 167
1

Regarding your concern

But soon I found that there's too much duplicated functor definations class xxx { public: void operator()() {...} }; in code and it looks awkward.

you should probably not be writing

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

but the version with struct where you save one line of syntactic clutter (public:) because members of structs are by default public:

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

which really, IMO, has rather little overhead compared to a simple function declaration.

Of course, the lambda version has a little less, and combined with a free templeate function, you also don't need decltype.

Wrt. to the lambda solution, one also must take into account that you can put the whole definition of the struct into a header file, while you cannot put the definition of the lambda object in a header file, if that header file is used from multiple translation units.

Of course the problem as stated rather looks like these definition would most likely be written inside a cpp file, so the lambda solution probably would works just as well.

Community
  • 1
  • 1
Martin Ba
  • 37,187
  • 33
  • 183
  • 337
  • -1: http://stackoverflow.com/questions/92859/what-are-the-differences-between-struct-and-class-in-c – Spook Jun 21 '13 at 08:29
  • @Spook - yeah, exactly. `struct` is default public, which is what the OP wanted. Where is the problem? – Martin Ba Jun 21 '13 at 08:36
  • He doesn't mind the public modifier, but the huge amount of unnecessary duplicated classes. Changing class into struct won't help. – Spook Jun 21 '13 at 08:38
  • @Spook: Nice to see you knowing what the OP minds and what not. – Martin Ba Jun 21 '13 at 08:39
  • "But soon I found that there's too much duplicated functor definitions in code and it looks awkward." ? Seems pretty straightforward to me. – Spook Jun 21 '13 at 08:40
  • @Sppok: Yeah, so I removed one line of the duplicated code -- which, given that the overhead vs. a normal function definition was 3 lines, now down to 2 lines, is a reduction of a swooping 33% in boilerplate. – Martin Ba Jun 21 '13 at 08:42
  • If function had 100 lines, it now would have 99, so effectively the gain is minimal. I guess the problem is, that classes are used to mimic the functions and that's the problem with quality of code. I removed the -1, but still, changing class to C-style struct is not a solution here. – Spook Jun 21 '13 at 08:47