2013-06-18 16 views
2

:표준 : 템플릿 매개 변수로 initializer_list 값은 내가 이런 일을하려고하고

template<typename enumType, 
     std::initializer_list<enumType> values, 
     std::initializer_list<std::string> mappings> 
struct enum_converter { 
    enumType toEnum(const std::string& literal) { ... } 
    std::string toString(const enumType value) { ... } 
}; 

나는 다음과 같이 사용하려는 :

enum test_enum {value_a, value_b}; 
struct test_enum_converter : public enum_converter< 
     test_enum, 
     {value_a, value_b}, 
     {"a", "b"}> {}; 

GCC는 저에게 말한다 :

class std::initializer_list<_Tp> is not a valid type 
for a template constant parameter. 

const을 유형에 추가해도 아무런 변화가 없습니다. 해결 방법이나 비슷한 해결책이 있습니까?

+0

, CONST 문자 포인터하지만 작동 할 것이다. –

+0

Im이 잘못되지 않았다면 const char은 전역으로 선언 된 경우에만 작동합니다. – Amadeus

답변

2

비 형식 템플릿 매개 변수로는 완전한 유형, 열거, 포인터 및 참조 만 사용할 수 있습니다. std::initializer_list은 그 중 하나입니다.

& 값을 템플릿 매개 변수로 사용해야합니까? 그것들을 생성자의 일반적인 매개 변수로 만들고 enum을 템플릿 매개 변수로 유지하는 것은 어떻습니까?

template<typename enumType> 
struct enum_converter { 
    static init(std::initializer_list<enumType> values, std::initializer_list<std::string> mappings) 
    { s_values = values; s_mappings = mappings; } 

    static enumType toEnum(const std::string& literal) { ... } 
    static std::string toString(const enumType value) { ... } 

private: 
    static std::initializer_list<enumType> s_values; 
    static std::initializer_list<std::string> s_mappings; 
}; 

한 번만 클래스를 사용하기 전에 init() 전화 : 여기

template<typename enumType> 
struct enum_converter { 
    enum_converter(std::initializer_list<enumType> values, std::initializer_list<std::string> mappings) : values(values), mappings(mappings) 

    enumType toEnum(const std::string& literal) { ... } 
    std::string toString(const enumType value) { ... } 

private: 
    std::initializer_list<enumType> values; 
    std::initializer_list<std::string> mappings; 
}; 

enum_converter<test_enum> test_enum_converter({...}, {...}); 

int main() 
{ 
    test_enum_converter.toEnum("bla"); 
} 

편집은 인스턴스가없는 대안이다. 특정 열거에 대해 둘 이상의 인스턴스가 필요한 경우

,이 같은 템플릿에 동음 매개 변수를 추가 할 수 있습니다 : 당신은 확실히 템플릿 인수로 문자열을 가질 수 없습니다

template <typename enumType, typename tag> 
struct enum_converter { /*as before*/ }; 

int main() 
{ 
    struct data_strings; 
    struct user_readable_strings; 
    enum_converter<test_enum, data_strings>::init({...}, {"a", "b"}); 
    enum_converter<test_enum, user_readable_strings>::init({...}, {"Option A", "Option B"}); 
} 
+0

예, 템플릿 매개 변수 여야합니다. 실제 코드에서 'test_enum_converter'는 변환을 위해 정적 메소드를 사용하는 SOCI 라이브러리의 유형 변환기입니다. – flyx

+0

@flyx 인스턴스가없는 버전을 추가했습니다. – Angew

+0

이 솔루션에 대해 싫어하는 중요한 점은 매핑 선언과 형식 선언을 구분한다는 것입니다. 이상적인 관점에서 컴파일 타임에 매핑 목록을 삽입하는 것이 좋습니다. 그러나이 버전은 Kerrek이 제안한 것보다 훨씬 더 읽기 쉽기 때문에, init를 정확히 한 번 호출하는 방법에 대해 설명하고 몇 가지 주장을 추가 할 것입니다. – flyx

1

포인터는 상수 표현식, 즉 extern linkage가있는 객체의 주소 인 경우에만 템플릿 인수가 될 수 있습니다.

typedef char const * charptype; 

template <int, charptype> struct item; 

template <typename ...> struct econv 
{ 
    static constexpr charptype convert(int) { return nullptr; } 
}; 

template <int I, charptype S, typename ...Tail> 
struct econv<item<I, S>, Tail...> 
{ 
    static constexpr charptype convert(int i) 
    { 
    return i == I ? S : econv<Tail...>::convert(i); 
    } 
}; 

#include <iostream> 
extern char const Hello[] = "Hello"; 
extern char const World[] = "World"; 

int main() 
{ 
    std::cout << econv< item<1, Hello> 
         , item<2, World> >::convert(2) 
    << "\n"; 
} 

익명의 이름 공간에 문자열을 넣고 헬퍼 매크로를 사용하여,이 방법은 흉보고 조금 정리 될 수 있습니다 그것은 그만한 가치가 있는지 통화 비록 다음 코드는 작동합니다.

관련 문제