Graznarak
Graznarak

Reputation: 3734

How to match set of template parameter characters

I am using Visual Studio 2013 RTM.

I am trying to write a variadic template that matches one of a number of characters. The recursive case is easy enough, but I am struggling with writing the base case.

template <char C, char... Cs>
auto char_match(char c) -> bool
{
    return c == C || char_match<Cs...>(c);
}

I tried the following as the base case, but it didn't work. I know that you can do this with class templates, and I was pretty certain that you can't do it with function templates.

template <>
auto char_match(char c) -> bool
{
    return false;
}

error C2912 : explicit specialization of 'bool char_match(char)' is not a specialization of a function template

I also tried using std::enable_if on the return type, but Microsoft doesn't like it.

template <char C, char... Cs>
typename std::enable_if<sizeof...(Cs) != 0, bool>::type char_match(char c)
{
    return c == C || char_match<Cs...>(c);
}

template <char C, char... Cs>
typename std::enable_if<sizeof...(Cs) == 0, bool>::type char_match(char c)
{
    return c == C;
}

error C2039: 'type' : is not a member of 'std::enable_if'

I would appreciate any suggestions on how to make this work.

Upvotes: 3

Views: 201

Answers (2)

Daniel Frey
Daniel Frey

Reputation: 56893

In your specific case, there is no reason for recursion, just use

template< char... Cs >
bool char_match( char c )
{
    constexpr const std::array< char, sizeof...( Cs ) > a {{ Cs... }};
    return std::find_if(std::begin(a), std::end(a),
                        [c](char x){return x==c;}) != std::end(a);
}

Not sure if VC++ will accept the code, but GCC and Clang do.

Live example

Upvotes: 3

Kerrek SB
Kerrek SB

Reputation: 477378

There isn't anything more specialized about your "specialization" than the main template, so that doesn't work. I think the easiest solution would be to use a class template:

template <char ...> struct char_match_impl;

template <> struct char_match_impl<>
{
    static bool go(char) { return false; }
};

template <char C, char ...Cs> struct char_match_impl<C, Cs...>
{
    static bool go(char c) { return c == C || char_match_impl<Cs...>::go(c); }
};

template <char ...Cs>
bool char_match(char c)
{ return char_match_impl<Cs...>::go(c); }

Upvotes: 5

Related Questions