Search code examples
c++c++11type-traitsstatic-assert

How can I use type traits to compare only the first template parameter in class that has multiple parameters?


So I have this function, GetProperty(), that is defined like the following:

template<typename T>
void GetProperty(T & val)

I want this to accept three possible values: bool, int, and a string class that has two template parameters. The string class, let's call it StringT, looks something like this:

template<typename CharType, size_t Size>
class StringT

I would like to be able to pass an instance of StringT to GetProperty() so that it only checks the CharType and allows any value for Size. For example, both of these calls should work without any extra specialization:

StringT<char, 512> str1;
GetProperty(str1);

StringT<char, 1024> str2;
GetProperty(str2);

The current implementation I have looks like this:

template<typename T>
void GetProperty(T & val)
{
    // Trying to use static_assert to only allow StringT values in the default implementation.
    static_assert(std::is_same<T, StringT<char, 512>>::value, "FAILED");

    // Do stuff
}

template<>
void GetProperty<bool>(bool & val)
{
    // Do stuff
}

template<>
void GetProperty<int>(int & val)
{
    // Do stuff
}

Obviously this doesn't work since it only allows a StringT<char, 512> type to be specified. Is there any way to ignore the 512 template parameter and have it accept any value for Size?


Solution

  • Option #1

    Provide a separate function overload for each type, so that you can accept any StringT<char, ?> in one of the overloads:

    template <size_t N>
    void GetProperty(StringT<char, N>& val) {}
    
    void GetProperty(bool val) {}
    
    void GetProperty(int val) {}
    

    DEMO 1

    Option #2

    Write your own type-trait:

    #include <type_traits>
    
    template <typename S, typename C>
    struct IsStringT : std::false_type {};
    
    template <typename C, size_t Size>
    struct IsStringT<StringT<C, Size>, C> : std::true_type {};
    
    template <typename T>
    void GetProperty(T & val)
    {
        static_assert(IsStringT<typename std::remove_cv<T>::type, char>{}, "FAILED");
    }
    
    template <>
    void GetProperty<bool>(bool & val) {}
    
    template <>
    void GetProperty<int>(int & val) {}
    

    DEMO 2