好的,我知道宏是邪恶的,应该不惜一切代价避免。我正在尝试减少重要的样板代码和重复,如果我不能将其宏化,就很难不犯错字。
这是一个有些人为的例子,因为我试图将我必须的真实代码简化为一个更简洁的例子。
#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 宏的“方法”参数时发生这种情况。我想在表中输入 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 ) ),
};