C ++ MACROS:条件代码包含在表达式NOT语句中

时间:2014-07-06 23:18:30

标签: c++ macros boost-preprocessor x-macros

好的,我知道宏是邪恶的,应该不惜一切代价避免。我试图减少重要的锅炉板代码和重复,如果我不能宏观化它将很难不犯错字错误。

这是一个有点人为的例子,因为我试图将实际代码减少到一个更简洁的例子。

#include <map>
#include <iostream>
#include <functional>
#include <boost/preprocessor/control/if.hpp>
#include <boost/preprocessor/comparison/equal.hpp>

using FUNC = std::function<int(int,int)>;

#define BINDIF( method ) BOOST_PP_IF(1,std::bind(&B::method, this, std::placeholders::_1,std::placeholders::_2),nullptr)
//                                   ^ this needs to vary on value of the method param
//                                   ^ I tried BOOST_PP_EQUAL(nullptr, method) here
//                                     it concatenated several Boost macros and threw
//                                     an error about not recognizing the long symbol
//                                     it created

#define TABLE       \
T(Add, add)         \
T(Sub, sub)         \
T(Mul, mul)         \
T(Div, div)

#define T(k,v) k,
enum Ops: size_t {
    TABLE
};
#undef T

class A {
public:
    FUNC Func;
    A(FUNC func)
        : Func(func) {
    }
};

class B {
    std::map<Ops,A> As;
public:
    int add(int x, int y) { return x + y; }
    int sub(int x, int y) { return x - y; }
    int mul(int x, int y) { return x * y; }
    int div(int x, int y) { return x / y; }

    B() {

        #define T(k,v) std::make_pair(Ops::k, A( BINDIF(v) ) ),
        As = {
            TABLE
        };
        #undef T
    }
};

int main() {
    return 0;
}

这将正确扩展在BINDIF宏中找到的std :: bind代码。但是,请注意第一个参数,条件,设置为1.如果我将此值更改为0,它会正确地删除值nullptr。问题是我想在评估传递给BINDIF宏的'method'参数时会发生这种情况。我想在表中输入nullptr值,因此不会生成std :: bind代码。

我完全清楚这个例子看起来有多么人为,但是我使用的大多数列的实际代码都有nullptr,因为我稀疏地绑定到4个std :: function指针之一。

以下是1:

的扩展
><(((º> g++ -E -g -O0 -Wall -std=c++11 test.cpp

...removed for brevity

class B {
    std::map<Ops,A> As;
public:
    int add(int x, int y) { return x + y; }
    int sub(int x, int y) { return x - y; }
    int mul(int x, int y) { return x * y; }
    int div(int x, int y) { return x / y; }

    B() {


        As = {
            std::make_pair(Ops::Add, A( std::bind(&B::add, this, std::placeholders::_1,std::placeholders::_2) ) ), 
            std::make_pair(Ops::Sub, A( std::bind(&B::sub, this, std::placeholders::_1,std::placeholders::_2) ) ), 
            std::make_pair(Ops::Mul, A( std::bind(&B::mul, this, std::placeholders::_1,std::placeholders::_2) ) ), 
            std::make_pair(Ops::Div, A( std::bind(&B::div, this, std::placeholders::_1,std::placeholders::_2) ) ),
        };

    }
};

int main() {
    return 0;
}

这是0:

的扩展
><(((º> g++ -E -g -O0 -Wall -std=c++11 test.cpp

...removed for brevity

class B {
    std::map<Ops,A> As;
public:
    int add(int x, int y) { return x + y; }
    int sub(int x, int y) { return x - y; }
    int mul(int x, int y) { return x * y; }
    int div(int x, int y) { return x / y; }

    B() {


        As = {
            std::make_pair(Ops::Add, A( nullptr ) ), 
            std::make_pair(Ops::Sub, A( nullptr ) ), 
            std::make_pair(Ops::Mul, A( nullptr ) ), 
            std::make_pair(Ops::Div, A( nullptr ) ),
        };

    }
};

int main() {
    return 0;
}

请原谅任何拼写错误以及此问题的总长度。我在最近几天搜索了这里和其他地方的答案,找不到任何似乎有用的东西。 Boost的宏文档很稀疏。

大笑,当然。具有nullptr的表格如下:

#define TABLE       \
T(Add, add)         \
T(Sub, sub)         \
T(Mul, mul)         \
T(Div, nullptr)

会产生如下代码:

As = {
    std::make_pair(Ops::Add, A( std::bind(&B::add, this, std::placeholders::_1,std::placeholders::_2) ) ), 
    std::make_pair(Ops::Sub, A( std::bind(&B::sub, this, std::placeholders::_1,std::placeholders::_2) ) ), 
    std::make_pair(Ops::Mul, A( std::bind(&B::mul, this, std::placeholders::_1,std::placeholders::_2) ) ),
    std::make_pair(Ops::Div, A( nullptr ) ),
};

1 个答案:

答案 0 :(得分:0)

好的,我认为这个问题无法通过MACROS解决。我认为此时需要模板元编程能力。对于任何感兴趣的人,我需要在编译时到passthru nullptr,或绑定到类方法。搜索继续......