Neal
Neal

Reputation: 81

How to implement a polymorphic function within member function in C++11?

I am using a framework written by others. The framework use some ugly macros. Firstly, the framework use macro to declare and define class like below:

#define DECLARE_FUNC(_name, _params) \
class _name                          \
{                                    \
    static int execute();            \
    static int exec_func(_params* param);          \
}

#define DEFINE_FUNC(_name, _params)  \
int _name::execute()                 \
{                                    \
    _params p = get_from_global();   \
    return exec_func(&p)             \
}                                    \
int _name::exec_func(_param* param)

when using this framework what I have to do is:

DECLARE_FUNC(foo, database)

DEFINE_FUNC(foo, database)
{
    // write business logic here        
}

when write the business logic, I have to query information from different tables in database and do almost the same thing with query results. The pseudo codes are like following:

TypeA a = TABLE(t_TypeA)->Query();
if (a.is_valid()) {
   // do something with a here
   // some local variables are used here
}

TypeB b = TABLE(t_TypeB)->Query();
if (b.is_valid()) {
   // do something with b here
   // some local variables are used here
}

Obviously there are too many duplicate codes, which is bad. So my colleague use macro to remove the duplicate codes. I think polymorphic lambda should work in this case, but C++11 doesn't support polymorphic lambda.

My question: is there any other ways to remove the duplicate code without macro?

Update: actually in source code "_params" is also a macro, it can expend to more parameters, I simplify it here. If expand the parameter macro and use polymorphic lambda, it looks like:

int ClassA::exec_func(Database database,
                      Date date,
                      Time time)
{
    // there are also some local variables, for example:
    long second = get_second(date, time);

    // polymorphic lambda version
    auto handle_table = [&](auto table_type) {
        // database, date, time and local variables will be used here
    }

    handle_table(TableA);
    handle_table(TableB);
    ...
    handle_table(TableX);
}

So Francis's solution may not work in this situation.

Upvotes: 1

Views: 110

Answers (1)

Jarod42
Jarod42

Reputation: 217720

lambdas can be written with class functors.

auto l = [&capture](auto param) {/*code*/};

becomes something like:

class MyFunctor
{
public:
    explicit MyFunctor(const capture_t& capture) : capture(capture) {}

    template <typename T>
    void operator () (T param) const { /* code */ }
private:
    const capture_t& capture; // or by value
};

and later

 auto l = MyFunctor(capture);

Upvotes: 1

Related Questions