를 OP 자신에 : 당신이 구문을 더 명확하게하기 위해 템플릿 별칭을 사용할 수 물론
//l is list<int,list<char,list<bool,nil>>>
using l = typename make_list<int,char,bool>::result;
솔루션을 사용하는 경우 전역 범위, 클래스 범위 또는 함수 범위에서만 작동합니다. 내 구현은 전역, 클래스 및 기능 범위 모두에서 작동합니다. OP 솔루션에 대한 또 다른 장점은 내 솔루션으로 여러 목록 START_LIST/END_LIST 쌍이 겹치도록 허용하는 것입니다. 즉, 서로 다른 목록 구성이 인터리빙 될 수 있습니다.
하나의 작은 제한은 starndard의 일부가 아닌 __COUNTER__
매크로를 사용하지만 gcc, clang 및 MSVC에서 잘 지원되므로 이식성이 큰 문제는 아닙니다. 또 다른 것은 함수 범위를위한 것입니다. 함수 오버플로 해상도를 사용하기 때문에 START_LIST_FUNC
과 ADD_TO_LIST_FUNC
이라는 별도의 매크로를 사용해야하지만 클래스 범위에서는 static
함수를 사용해야하지만 함수 범위에서는 static
함수를 선언 할 수 없습니다.
편집 : OP의 주석에서 ListReverseHelper라는 아이디어를 통합하여 훨씬 간단하게 만듭니다. ++ g에서 컴파일
#include <iostream>
#include <typeinfo>
using namespace std;
struct Nil {};
template <typename T, typename U> struct Cons {};
template <typename List, typename Reversed> struct ListReverseHelper;
template <typename Reversed>
struct ListReverseHelper<Nil, Reversed> {
using Type = Reversed;
};
template <typename Head, typename Tail, typename Reversed>
struct ListReverseHelper<Cons<Head, Tail>, Reversed> {
using Type = typename ListReverseHelper<Tail, Cons<Head, Reversed>>::Type;
};
template <typename T, int N> struct ListMakerKey : ListMakerKey<T, N-1> {};
template <typename T> struct ListMakerKey<T, 0> {};
#define START_LIST_(name, modifier) \
struct name##_ListMaker {}; \
modifier Nil list_maker_helper_(ListMakerKey<name##_ListMaker, __COUNTER__>);
#define ADD_TO_LIST_(name, type, modifier) \
modifier Cons<type, decltype(list_maker_helper_(ListMakerKey<name##_ListMaker, __COUNTER__>{}))> \
list_maker_helper_(ListMakerKey<name##_ListMaker, __COUNTER__>);
#define END_LIST(name) \
using name = typename ListReverseHelper<decltype(list_maker_helper_(ListMakerKey<name##_ListMaker, __COUNTER__>{})), Nil>::Type;
#define START_LIST(name) START_LIST_(name, static)
#define ADD_TO_LIST(name, type) ADD_TO_LIST_(name, type, static)
#define START_LIST_FUNC(name) START_LIST_(name,)
#define ADD_TO_LIST_FUNC(name, type) ADD_TO_LIST_(name, type,)
START_LIST(List)
ADD_TO_LIST(List, int)
int a = 10;
ADD_TO_LIST(List, float)
int b = 10;
START_LIST(List2)
ADD_TO_LIST(List, int)
int c = 10;
ADD_TO_LIST(List2, float)
ADD_TO_LIST(List, double)
ADD_TO_LIST(List2, int)
ADD_TO_LIST(List2, float)
END_LIST(List2)
ADD_TO_LIST(List, double)
ADD_TO_LIST(List, char)
END_LIST(List)
struct A {
START_LIST(List3)
ADD_TO_LIST(List3, int)
int a = 10;
ADD_TO_LIST(List3, float)
int b = 10;
ADD_TO_LIST(List3, double)
ADD_TO_LIST(List3, int)
END_LIST(List3)
};
int main() {
START_LIST_FUNC(List4)
ADD_TO_LIST_FUNC(List4, char)
int a = 10;
ADD_TO_LIST_FUNC(List4, float)
int b = 10;
ADD_TO_LIST_FUNC(List4, int)
ADD_TO_LIST_FUNC(List4, char)
END_LIST(List4)
List x;
List2 y;
A::List3 z;
List4 w;
cout << typeid(x).name() << endl;
cout << typeid(y).name() << endl;
cout << typeid(z).name() << endl;
cout << typeid(w).name() << endl;
}
-4.8은 :
[hidden]$ g++ -std=c++11 x.cpp && c++filt -t `./a.out`
Cons<int, Cons<float, Cons<int, Cons<double, Cons<double, Cons<char, Nil> > > > > >
Cons<float, Cons<int, Cons<float, Nil> > >
Cons<int, Cons<float, Cons<double, Cons<int, Nil> > > >
Cons<char, Cons<float, Cons<int, Cons<char, Nil> > > >
나는 컴파일러에 의존 할 것이라고 생각한다. 어떤 컴파일러를 사용하고 있습니까? 나는 나의 마지막 직업에서 그와 비슷한 것을 보았다. 슬프게도, 나는 세부 사항을 기억하지 않는다. – abelenky
@abelenky 표준 C++ 11 솔루션을 기대하고 있습니다.하지만 G ++ 4.8에서 작동하는 것과 함께 할 것이라고 생각합니다. –
내 대답을 좋아할 수도 있습니다 : http://stackoverflow.com/questions/18701798/building-and-accessing-a-list-of-types-at-compile-time/18704609#18704609 –