4

는 가변 인자 템플릿은 간단 갖는 매개 변수, 그것은 일부 char s의 string_constantTStringConstant 받아 들일 것, 그래서 나는 그것을 전문으로 할 수 있습니다C++는 가변 인자 템플릿의 가변 수는

template <typename TStringConstant, typename TValue> 
class entry; 

template <char... key, typename TValue> 
class entry<string_constant<key...>, TValue>{} 

내가 만들고 싶었다 경우를 다른 char s의 TStringConstant s의 가변 개수를 허용하는 템플릿 클래스는이를 수행하는 방법이 있습니까? 아마도 템플릿 템플릿 매개 변수가 있습니까?

다음 모두 유효 할 것이다 그래야 : 그것은 컴파일에 실패합니다 entry_list<something_else<'c','b','a'>> 단지 entry<something_else<'c','b','a'>, bool>처럼 거부합니다

entry_list<string_constant<'c','b','a'>, string_constant<'d','e','f','g'>>(); 
entry_list<string_constant<'c','b','a'>, string_constant<'d','e','f','g'>, string_constant<'d','e','z','z'>>(); 
entry_list<string_constant<'a','b','c'>>(); 

보너스합니다.

답변

3

static_assert으로 할 수 있습니다. 나는 그것을 친숙한 방식으로 구현하는 방법을 모르지만, 당신이 그것에 대해 신경 쓰지 않는다고 생각합니다.

그래서 여기 간다 :

template <class... Args> struct entry { 
    static_assert(are_string_constant<Args...>::value, "invalid template args for entry"); 
}; 

auto test() 
{ 
    entry<string_constant<'c', 'd'>> e1; // OK 
    entry<string_constant<'c', 'd'>, string_constant<'a', 'b', 'c', 'd'>> e2; // OK 

    // entry<int, 
    //  string_constant<'c', 'd'>, 
    //  string_constant<'a', 'b', 'c', 'd'>> e3; // static_assert kicks in 

    // entry<definitely_not_string_constant<'c', 'd'>, 
    //  string_constant<'a', 'b', 'c', 'd'>> e4; // static_assert kicks in 


} 

are_string_constant의 건물은 꽤 정직 : C에서

template <char... Args> struct string_constant {}; 
template <char... Args> struct definitely_not_string_constant {}; 

// --- is_string_constant ----- 

template <class T> struct is_string_constant : std::false_type {}; 

template <char... Args> 
struct is_string_constant<string_constant<Args...>> : std::true_type {}; 

// --- are_string_constant -----  

template <class... Args> struct are_string_constant; 

template <class A0, class... Args> 
struct are_string_constant<A0, Args...> 
    : std::integral_constant<bool, (is_string_constant<A0>::value && 
            are_string_constant<Args...>::value)>::type 
{}; 

template <class T> struct are_string_constant<T> : is_string_constant<T>::type {}; 

++ (17) 구현이 fold expressions와 쉽게 (당신 때문에 돈 are_string_constant 필요) :

template <class... Args> 
struct entry { 
    static_assert((... && is_string_constant<Args>::value), 
        "invalid template args for entry"); 
}; 
0

내가보기에 실제 문제는 다음과 같습니다. entry_list 클래스의 가변 문자 목록을 어떻게 사용 하시겠습니까?

나는 볼로프의 해결책 (+1)을 좋아하지만 재귀적인 해결책을 받아들이면 상속의 사용을 제안합니다.

다음은 사용 상속을 원하지 않는 경우

template <char ... keys, typename ... Scs> 
class entry_list<string_constant<keys ...>, Scs ...> 
{ static_assert(sizeof(entry_list<Scs...>), "!"); }; 
다음 대신, 당신은 static_assert()을 사용할 수 있습니다

template <char ...> 
struct string_constant 
{ }; 

template <char ...> 
struct something_else 
{ }; 

template <typename ...> 
class entry_list; 

template <> 
class entry_list<> 
{ }; 

template <char ... keys, typename ... Scs> 
class entry_list<string_constant<keys ...>, Scs ...> 
    : public entry_list<Scs ...> 
{ }; 

int main() 
{ 
    entry_list<string_constant<'c','b','a'>, 
       string_constant<'d','e','f','g'>>(); // compile 

    entry_list<string_constant<'c','b','a'>, 
       string_constant<'d','e','f','g'>, 
       string_constant<'d','e','z','z'>>(); // compile 

    entry_list<string_constant<'a','b','c'>>(); // compile 

    //entry_list<something_else<'c','b','a'>>(); // compilation error 

    //entry_list<string_constant<'c','b','a'>, bool>(); // compilation error 
} 

전체 예입니다