2017-01-27 12 views
2

내 프로젝트에서 나는 boost::anyboost::variant을 철저히 사용하고 있습니다. 이를 위해 이전의 질문에서 에서 boost::variant까지 일반적인 변환 루틴을 고안했습니다. Generic function to convert boost::any to boost::variant. 사람들을 도와 주신 많은 분들께 감사드립니다.부스트 전처리를 사용하는 부스트 변형 부스트

발견 된 솔루션은 아무 문제없이 나를 위해 일했지만 심각한 단점이있었습니다. 완전히 templatized 솔루션에 의해 생성 된 코드 부 풀림은 금지 될 수 있으며 간단한 변환에는 불필요한 경우가 있습니다. (나는 컴파일 시간을 언급하지 않았다.)

이제 쉽게 (일반이 아닌) 변환을 위해 템플릿 전문화 작업을 할 생각이 들었지만, 지루하고 오류가 발생하기 쉬운 코드를 발견했다. 특히,이 작업을 반복해서해야하는 경우.

다음 코드 조각은 문제를 보여줍니다. 일반적인 응용 프로그램에서는 20 가지 이상의 유형이있을 수 있습니다.

#include <boost/preprocessor.hpp> 
#include <boost/variant.hpp> 
#include <boost/any.hpp> 
#include <boost/optional.hpp> 
#include <iostream> 

template<typename VARIANT> 
boost::optional<VARIANT> anyToVariant(const boost::any& any) { 
    boost::optional<VARIANT> ret; 
    // General implementation omitted. 
    // The implementation is lengthy and produces an enormous code bloat. In some cases it is the best solution. 
    return ret; 
} 

// Specialized Template reduces code bloat. But is error-prone to type write for every new variant type. 
template<> 
boost::optional <boost::variant<int, double, std::string>> anyToVariant(const boost::any& any) { 
    boost::optional<boost::variant<int, double, std::string>> ret; 
    if (any.type() == typeid(int)) { 
     ret = boost::any_cast<int>(any); 
    } 
    if (any.type() == typeid(double)) { 
     ret = boost::any_cast<double>(any); 
    } 
    if (any.type() == typeid(std::string)) { 
     ret = boost::any_cast<std::string>(any); 
    } 
    return ret; 
} 

// Should be implemented with boost preprocessor 
#define BOOST_ANY_TO_VARIANT(TypeList) 

// Better would be a macro like this 
BOOST_ANY_TO_VARIANT(int, double, std::string); // Create the above template specialization 

int main() { 
    boost::variant<int, double, std::string> v; 
    boost::any x = 4; 
    v=*anyToVariant<boost::variant<int, double, std::string>>(x); 
} 

더 나은 솔루션은 물론 매크로 것,하지만 불행히도 나는 boost-preprocessor로이 매크로를 실행 할 수 없습니다. 나는 아직 기술이 부족하지만 끝낼 수 있다고 확신합니다.

boost-preprocessor에서 경험이있는 사람이라면 누구든지 내 문제를 해결할 수 있습니까? 내가 상상할 수

가장 좋은 방법은 매크로 다음과 같이 될 것이다 :

#define BOOST_ANY_TO_VARIANT(VariantType) \ 
// Magic? 

typedef boost::variant<int, std::string, double> MyVariant; 

BOOST_ANY_TO_VARIANT(MyVariant) 

하지만이 솔루션을 달성 할 것을 의심한다. 여기

+0

그래서, 단지 명확하게하기 위해, 매크로의 목표는 템플릿 특수화의 정의를 생성하는 것입니다, * boost * any를 그 자리에서 변환하지 않습니까? – Quentin

+0

있습니다. 매크로는 위 코드를 생성해야합니다. – Aleph0

답변

2

당신이 이동 :

#define ANY_TO_VARIANT_OP_VARIANT(typeSeq) \ 
    boost::optional<boost::variant<BOOST_PP_SEQ_ENUM(typeSeq)>> 

#define ANY_TO_VARIANT_CONVERT_AND_RETURN(r, data, elem) \ 
    if (any.type() == typeid(elem)) { \ 
     return Ret{boost::any_cast<elem>(any)}; \ 
    } 

#define SPECIALIZE_BOOST_ANY_TO_VARIANT(typeSeq) \ 
    template<> \ 
    ANY_TO_VARIANT_OPT_VARIANT(typeSeq) anyToVariant(const boost::any& any) { \ 
     using Ret = ANY_TO_VARIANT_OPT_VARIANT(typeSeq); \ 
     BOOST_PP_SEQ_FOR_EACH(ANY_TO_VARIANT_CONVERT_AND_RETURN, ~, typeSeq) \ 
     return Ret{}; \ 
    } 

사용법 :

SPECIALIZE_BOOST_ANY_TO_VARIANT((int)(double)(std::string)) 

See it live on Coliru

+0

많은 감사. 당신의 해결책을 확인하겠습니다. 'boost-preprocessor'를 좀 더 다루어야 할 것 같습니다. 해결책은 예상보다 짧았습니다. – Aleph0

+0

나는 BOOST_PP_REMOVE_PARENS조차 알지 못했습니다! 이것은 이미 제가 진전을 이루지 못했던 요점이었습니다. – Aleph0

+0

@FrankSimon 나는 또한 당신이'BOOST_PP_SEQ_ENUM (typeSeq)'을 사용할 수 있다고 생각한다. – llonesmiz