2014-10-02 9 views
1

부스트 MPL과 퓨전을 사용하여 Java와 유사한 주석 시스템을 구현하려고합니다.C++ 컴파일시 클래스 멤버 var에

왜 필요합니까 : 몇 가지 특별한 런타임 기능을 사용하려면 var 멤버에 주석을 달아야합니다.

class foo 
{ 
    INIT() 

    $REGISTER("test1") 
    int test1 = 5; 

    $REGISTER("b") 
    char* b = "rndmText"; 

    .... 
} 

내 목표는 포인터의 조합 $ REGISTER 같은 텍스트입니다 (& A, "A")하지만 미래 목표입니다 : 내가 이렇게 내 기본 clase에 컴파일 시간에 그들을 시도 등록합니다. ..

기본 클래스는 필요한 모든 것을 처리합니다.

#define INIT() \  
typedef boost::fusion::vector0<> BOOST_PP_CAT(registered, BOOST_PP_SUB(__COUNTER__,2)); \ 
boost::fusion::vector0<> BOOST_PP_CAT(list,BOOST_PP_SUB(__COUNTER__,2)); 

#define EXPORT(arg) \ 
typedef boost::fusion::result_of::push_back< BOOST_PP_CAT(registered, BOOST_PP_SUB(__COUNTER__,4)), const char*>::type BOOST_PP_CAT(registered, __COUNTER__); \ 
BOOST_PP_CAT(registered, BOOST_PP_DEC(__COUNTER__)) BOOST_PP_CAT(list, BOOST_PP_SUB(__COUNTER__,1)) = boost::fusion::make_list(BOOST_PP_CAT(list,BOOST_PP_SUB(__COUNTER__,7)), arg); 

이 (내 경우) 확장에 : 레지스터 매크로는 융합 벡터 생성

typedef boost::fusion::vector0<> registered18; 
    boost::fusion::vector0<> list19;; 

    typedef boost::fusion::result_of::push_back< registered18, const char*>::type registered23; 
    registered23 list24 = boost::fusion::make_list(list19, "test1");; 
    int test1 = 5; 

    typedef boost::fusion::result_of::push_back< registered23, const char*>::type registered28; 
    registered28 list29 = boost::fusion::make_list(list24, "b");; 
    char* b = "rndmText";; 

을 그리고 여기에 문제가 : 부스트 :: 융합 :: make_list은 (... , "test1") 컴파일러 오류를 만들고 그것을 수정하는 방법을 모르겠습니다. 이것은 오류입니다 :

boost::fusion::joint_view<Sequence,const boost::fusion::single_view<const char *>>::joint_view(const boost::fusion::joint_view<Sequence,const boost::fusion::single_view<const char *>> &)' : cannot convert argument 1 from 'boost::fusion::list<T,const char (&)[6],boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_,boost::fusion::void_>' to 'const boost::fusion::joint_view<Sequence,const boost::fusion::single_view<const char *>> &' 

누군가 저를 도울 수 있습니까? 아니면 더 좋은 생각이 있습니까?

도미니크

답변

3

이 정말 (죄송합니다) 컴파일 오류와 함께 도움이되지 않고는 코멘트를 너무 오래했다.

Can someone help/or have a better idea?

나는 매크로를 남용하고 있다고 생각합니다. 대신 클라이언트 코드를 고려해

class foo: public registered<foo> { 

    int test1 = 5; 
    char* b = "rndmText"; 

public: 
    foo(); 
    virtual ~foo() = default; 
}; 

foo::foo() : registered<foo>{ "foo" } { 
    register(&i, "i"); // part of the interface of the base class 
    register(&b, "b"); 
} 

설명 :

같은 기능은 이제 기본 클래스에 의해 제공된다. CRTP 구현은 registered에서 상속 한 두 개 이상의 클래스가있는 경우 동일한 클래스 계층 구조에 속하지 않음을 의미합니다. 메타 데이터의 지정이 관련없는 구체적인 클래스 사이에 클래스 관계를 적용해서는 안되기 때문입니다.

registered<T>의 구현은 (당신이 그것을 필요로하는 경우에 또는 뭔가 다른) 내부 boost::fusion를 사용할 수 있고 삼m에게 편리한 별칭 (예를 들어, using data_sequence = boost::fusion::vector0<>) 뒤에 긴 선언을 숨길 수 있습니다.

INIT() 부분은 자연스럽게 registered<T> 인스턴스 (및 공용 인터페이스)를 구성합니다.

이 구현은 매크로를 완전히 피할 수 있으며 API를 registered<T>에서 가져 오기 만하면 클라이언트 코드에 더 쉽게 메타 데이터를 표시 할 수 있습니다.

+0

이것은 내 첫 번째 (게시되지 않은) 솔루션과 매우 비슷합니다. 매크로를 사용하여 가독성을 높이기 위해 클래스 멤버 선언과 가까운 레지스터 함수를 이동 시키길 바랍니다. – Matyro

+0

@Matyro : 고귀한 목표처럼 들리지만, 당신이 썼던 매크로가 가독성에 도움이되지는 않는다고 생각합니다. –

+0

배경 소스는 덜 중요한 사람들을위한 것으로, 앞면이 잘 보일 것입니다 : p – Matyro