나는 Andrei Alexandrescu의 Modern C++ 디자인을 읽으며 자신이 제공하는 형식 목록 예제 중 일부를 사용하려고합니다. 아래 예제에서는 형식 및 정수를 보유하는 Option
구조체 목록을 만들려고합니다. 나중에 해당 옵션의 유형 목록을 만든 다음 정수와 함께 다른 구조체 FindTypeForMapping
에 전달하려고합니다. 정수가 옵션 목록에 설정된 정수 중 하나와 일치하면 식은 해당 옵션의 유형으로 평가되어야합니다. 그렇지 않으면 내 사용자 정의 유형 NullType
으로 평가됩니다. 작동매크로 대신 템플릿 매개 변수 팩 사용
첫 번째 방법은 OptionsList
이 매크로를 만들어 졌는지, 그리고 거기에 내가 n
Option
의 각 매크로 n-1
Option
초 동안 매크로를 사용하는 목록을 보유하고 있음을 Option
의 각 번호에 대한 매크로를 가지고있다.
그런 다음 템플릿 매개 변수의 매개 변수 팩을 목록에 사용하고 싶습니다. 이 버전의 목록은 OptionsList2
입니다. OptionsList2
에서 재귀 적으로 목록을 작성하지만이 목록을 FindTypeForMapping
에 전달할 때 컴파일 시간 오류가 발생합니다 (아래 참조).
struct NullType { };
template<class T, class U>
struct OptionsList
{
typedef T Head;
typedef U Tail;
};
template<class T, class... U>
struct OptionsList2
{
typedef T Head;
typedef typename std::conditional<sizeof...(U) == 0, NullType, OptionsList2<U...>>::type Tail;
};
template<int n, typename N>
struct Option
{
enum {
int_mapping = n
};
typedef N MappedType;
};
template<int, int> struct CheckMappedInt;
template<int n>
struct CheckMappedInt<n, n>
{
enum { is_the_same = 1};
};
template<int n, int m>
struct CheckMappedInt
{
enum { is_the_same = 0};
};
template<typename OLT, int n> struct FindTypeForMapping;
template<int n>
struct FindTypeForMapping<NullType, n>
{
typedef NullType mapped_type;
};
template<typename OP, typename Tail, int n>
struct FindTypeForMapping<OptionsList<OP, Tail>, n>
{
private:
enum {temp = CheckMappedInt<OP::int_mapping, n>::is_the_same };
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
public:
typedef typename std::conditional<
temp == 1,
typename OP::MappedType,
temp_type>::type mapped_type;
};
// Added this after SoryTellers comment
template<typename OP, typename Tail, int n>
struct FindTypeForMapping<OptionsList2<OP, Tail>, n>
{
private:
enum {temp = CheckMappedInt<OP::int_mapping, n>::is_the_same };
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
public:
typedef typename std::conditional<
temp == 1,
typename OP::MappedType,
temp_type>::type mapped_type;
};
#define OPTION_LIST_1(op1) OptionsList<op1, NullType>
#define OPTION_LIST_2(op1, op2) OptionsList<op1, OPTION_LIST_1(op2)>
#define OPTION_LIST_3(op1, op2, op3) OptionsList<op1, OPTION_LIST_2(op2, op3)>
#define OPTION_LIST_4(op1, op2, op3, op4) OptionsList<op1, OPTION_LIST_3(op2, op3, op4)>
#define OPTION_LIST_5(op1, op2, op3, op4, op5) OptionsList<op1, OPTION_LIST_4(op2, op3, op4, op5)>
#define OPTION_LIST_6(op1, op2, op3, op4, op5, op6) OptionsList<op1, OPTION_LIST_5(op2, op3, op4, op5, op6)>
#define OPTION_LIST_7(op1, op2, op3, op4, op5, op6, op7) OptionsList<op1, OPTION_LIST_6(op2, op3, op4, op5, op6, op7)>
#define OPTION_LIST_8(op1, op2, op3, op4, op5, op6, op7, op8, op9) OptionsList<op1, OPTION_LIST_7(op2, op3, op4, op5, op6, op7, op8)>
#define OPTION_LIST_9(op1, op2, op3, op4, op5, op6, op7, op8, op9) OptionsList<op1, OPTION_LIST_8(op2, op3, op4, op5, op6, op7, op8, op9)>
int main(int argc, char* argv[])
{
typedef Option<1, char> o1;
typedef Option<2, int> o2;
// Works
typedef OPTION_LIST_2(o1, o2) ol;
typedef typename FindTypeForMapping<ol, 1>::mapped_type ResolvedType; // Works
typedef OptionsList2<o1, o2> ol2;
typedef typename FindTypeForMapping<ol2, 1>::mapped_type ResolvedType2;
/*
error: invalid use of incomplete type ‘struct FindTypeForMapping<Option<2, int>, 1>’
typedef typename FindTypeForMapping<Tail, n>::mapped_type temp_type;
*/
}
간단하게 쓸 수있다 에러 메시지가 얼마나 복잡한 지에 관계없이'OptionsList2' 만 허용하는'FindTypeForMapping'과'OptionsList' 만 허용한다는 점은 분명히 이해할 수 있습니다. 그것들은 ** 다른 ** 템플릿입니다! – StoryTeller
네, 고마워요. 나는 OptionsList2를 받아들이는 FindTypeMapping의 복사본을 추가했다. 여전히 오류는 있지만 약간 다릅니다. /* 오류 : 불완전한 유형의 'struct FindTypeForMapping
잘못된 방식으로 진행되는 IMO. 물건을 복제하는 대신 매크로 제거에 집중하십시오. 'OptionsList'를':: type'으로 드러내는'MakeOptionList'메타 함수를 추가하십시오. 그런 다음 매크로를 제거합니다. –
StoryTeller