2014-07-06 5 views
-3

매크로 매크로는 악의적 인 것으로 알고있어 야하며 회피해야합니다. 중요한 보일러 플레이트 코드와 반복을 줄이기 위해 노력하고 있습니다. 매크로화 할 수없는 경우 오타를 범하지 않기가 어렵습니다.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)), 
}; 
+5

주의 지속 기간이없는 사람을 위해, 최종 구문의 내용과 수행해야 할 작업에 대한 매우 간단하고 짧은 의사적인 예를 추가 할 수 있습니까? –

+0

테이블이 결과 코드에 어떻게 영향을 미칠지를 보여주는 부록을 추가했습니다 ... –

+0

0 또는 1 대신 BOOST_PP_EQUAL (nullptr, method)을 사용했지만 부스트 매크로를 연결 한 다음 말하지 않습니다. 있다. –

답변

0

좋아, 나는이 문제 매크로를 통해 해결 못하는 생각합니다. 나는이 시점에서 템플리트 메타 프로그래밍 능력이 필요하다고 생각한다. 누구든지 관심이 있으시면 컴파일 시간에을 passthru nullptr 또는 클래스 메소드에 바인드해야합니다. 검색은 계속됩니다 ...