Search code examples
c++c++11variadic-templatesnon-type-template-parameter

Non-type template parameter with template parameter pack


I am checking the validity of a string whose valid values are known at compile time. I have the following simplified code snippet:

#include <cassert>
#include <string>

template <char const* const _Rhs, char const* const _Rhs2,
          char const* const _Rhs3>
bool IsValid(std::string const& _Lhs) {
    return _Rhs == _Lhs or _Rhs2 == _Lhs or _Rhs3 == _Lhs;
}

template <char const* const _Rhs, char const* const _Rhs2>
bool IsValid(std::string const& _Lhs) {
    return _Rhs == _Lhs or _Rhs2 == _Lhs;
}

template <char const* const _Rhs>
bool IsValid(std::string const& _Lhs) {
    return _Rhs == _Lhs;
}

static const char record[] = "record";
static const char replay[] = "replay";
static const char idle[] = "idle";

int main() {
    assert((IsValid<record>("record")));
    assert((IsValid<record, replay>("replay")));
    assert((IsValid<record, replay, idle>("idle")));
    assert((not IsValid<record, replay, idle>("unknown")));
}

Is there a way I could generalize the IsValid function to take an arbitrary number of template parameters?

Something like:

template <char const* const _Rhs, typename... Args>
bool IsValid(std::string const& _Lhs) {
    return _Rhs == _Lhs or IsValid<Args...>(_Lhs);
}

Solution

  • template<char const* str>
    struct str_t {
      static const char* string = str;
    };
    bool IsValidImpl(std::string const& str) {
      return false;
    }
    template<class String, class...Strings>
    bool IsValidImpl(std::string const& str, String, Strings... strings) {
      return (str == String::string) || IsValidImpl( str, strings... );
    }
    template<class...Strings>
    bool IsValid(std::string const& str) {
      return IsValidImpl(str, Strings{}...);
    }
    
    assert((IsValid<str_t<record> >("record")));
    assert((IsValid<str_t<record>, str_t<replay> >("replay")));
    assert((IsValid<str_t<record>, str_t<replay>, str_t<idle> >("idle")));
    assert((not IsValid<str_t<record>, str_t<replay>, str_t<idle> >("unknown")));
    

    there are much cleaner ways to do this in and , but this is a solution as required.