2011-12-08 6 views
1

얼마나 많은 템플릿 인수가 비어 있는지를 알려주는 boost::mpl::eval_if (또는 유사한 함수)의 결과에 따라 일부 인수가있는 매크로를 호출하려고합니다. 내가 인수 EmptyType을 얼마나 많은에 따라 일부 콘텐츠와 함께 내 수업을 채우기 위해 노력하고boost :: mpl을 사용하면 얼마나 많은 템플릿 클래스가 "비어 있지"않은지를 알 수 있으며이 숫자로 일부 매크로를 호출 할 수 있습니까?

struct EmptyType { }; 
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType> 
class my_class 
{ 
    eval_if<is_not_same<arg1, EmptyType>, FILL_MY_CLASS_DEFINE(1)> else  
    eval_if<is_not_same<arg2, EmptyType>, FILL_MY_CLASS_DEFINE(2)> else 
    eval_if<is_not_same<arg3, EmptyType>, FILL_MY_CLASS_DEFINE(3)>; 
}; 

: 우리는 다음과 같은 몇 가지 의사가 있다고. Boost.MPL/Preprocessor 또는 다른 Boost 라이브러리를 통해 어떻게 C++ 03에서 그렇게 할 수 있는지 궁금합니다.

+0

사전 처리기가 먼저오고 원시 텍스트 대체를 정의하므로 (전처리 기) 및 템플릿 코드 (컴파일러)가 잘 작동하지 않습니다. – Xeo

답변

2

전처리 기나 mpl이 필요 없습니다.

편집를이 C++ 03에서 작동 라이브를 참조하십시오 : https://ideone.com/6MaHJ

#include <iostream> 
#include <string> 

struct EmptyType { }; 

template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType> 
class my_class 
{ 
    // FILL_MY_CLASS_DEFINE(3) 
}; 
template<class arg1, class arg2> 
class my_class<arg1,arg2,EmptyType> 
{ 
    // FILL_MY_CLASS_DEFINE(2) 
}; 
template<class arg1> 
class my_class<arg1,EmptyType,EmptyType> 
{ 
    // FILL_MY_CLASS_DEFINE(1) 
}; 
template<> 
class my_class<EmptyType,EmptyType,EmptyType> 
{ 
    // FILL_MY_CLASS_DEFINE(0) 
}; 

int main(int argc, const char *argv[]) 
{ 
    my_class<std::string, double, int> a; 
    my_class<std::string, int> b; 
    my_class<void> c; 

    return 0; 
} 
+0

C++ 03에서 작동합니까? – myWallJSON

+0

@myWallJSON 예, edit 및 https://ideone.com/6MaHJ를 참조하십시오. – sehe

1

당신은 가변 인자 템플릿을 찾고 계십니까 부분 특수화는 당신이 필요로하는 무엇입니까?

#include <tuple> 
#include <iostream> 
#include <string> 

template <typename... Arg> 
struct my_class 
{ 
    // getting the size of the argument list: 
    enum { size = sizeof...(Arg) }; // in absense of static fields with initializers... 

    // demo filling the struct with data: 
    std::tuple<Arg...> arg_data; 
    my_class(Arg&&... a) : arg_data(std::forward<Arg>(a)...) { } 
}; 

int main(int argc, const char *argv[]) 
{ 
    my_class<std::string, int> a("hello world", 42); 

    std::cout << "size: " << a.size << std::endl; 
    std::cout << "last: " << std::get<a.size-1>(a.arg_data) << std::endl; 

    return 0; 
} 

출력 : 당신이 많은 템플릿 인수를 할 때

size: 2 
last: 42 
+0

variadic 템플릿은 C++ 11과 함께 제공됩니다. – myWallJSON

+0

@myWallJSON : 당신은 옳습니다. 나는 어떻게 든 그 요구를 놓쳤다. (_ 이미 경험이 있으시다면, Boost Preprocess_를 사용하여 가변성 템플릿의 일부 용도를 에뮬레이션 할 수 있습니다.) – sehe

0

, 부분적인 전문성이 비실용적이고 오류가 발생하기 쉬운 수 있습니다. 아래 코드는 원하는대로 할 수 있지만 다른 답변에서 이미 언급했듯이 항상 최선의 방법은 아닙니다.

#include <boost/mpl/count_if.hpp> 
#include <boost/mpl/not.hpp> 
#include <boost/type_traits/is_same.hpp> 

using boost::is_same; 
using boost::mpl::_; 
using boost::mpl::not_; 
using boost::mpl::count_if; 

#define FILL_MY_CLASS_DEFINE(x) static const int __x__ = x // an example, watch out: no semicolon at the end 

struct EmptyType { }; 
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType> 
class my_class 
{ 
    // count the types which are not equal to EmptyType 
    static const long NonEmptyCount = count_if<type, not_<is_same<_, EmptyType> > >::value; 
    // invoke a macro with an argument 
    FILL_MY_CLASS_DEFINE(NonEmptyCount); 
};