매크로 매크로는 악의적 인 것으로 알고있어 야하며 회피해야합니다. 중요한 보일러 플레이트 코드와 반복을 줄이기 위해 노력하고 있습니다. 매크로화 할 수없는 경우 오타를 범하지 않기가 어렵습니다.C++ MACROS : 조건부 코드에 NOT 문이 포함되어 있음
좀 더 간결한 예제를 사용하여 실제 코드를 줄이려고 시도한 것처럼 다소 고생 된 예제입니다.
#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 포인터 중 하나에 드문 드문 바인딩됩니다.
><(((º> 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;
}
는 오타 및이 질문의 전체 길이를 용서하십시오 : 여기에 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(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;
}
: 여기
1과 확장이다. 나는 지난 며칠 동안 여기와 다른 곳에서 답을 찾았고 아무 것도 찾을 수 없었다. 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)),
};
주의 지속 기간이없는 사람을 위해, 최종 구문의 내용과 수행해야 할 작업에 대한 매우 간단하고 짧은 의사적인 예를 추가 할 수 있습니까? –
테이블이 결과 코드에 어떻게 영향을 미칠지를 보여주는 부록을 추가했습니다 ... –
0 또는 1 대신 BOOST_PP_EQUAL (nullptr, method)을 사용했지만 부스트 매크로를 연결 한 다음 말하지 않습니다. 있다. –