Search code examples
c++11overloadingstatic-assert

static_assert triggering during function name resolution


The following code will static_assert when calling the member function A::Get with a string literal, presumably because the function overloading naming resolution must instantiate the template regardless of whether it is selected.

template<typename T>
struct helper
{
    static_assert(std::is_integral<T>::value, "Must be integeral type");

    typedef T type;
};

class A
{
public:
    A()
    {}

    std::string Get(const char* value) const
    {
        return std::string(value) + " (non-template)";
    }

    template<typename T>
    typename helper<T>::type Get(T value) const
    {
        return value;
    }
};

I can stop the assert by adding a 'helper' specialization, however there are other situations where the helper class is used, and it doesn't make sense to specialize for 'const char*' in other situations.

Is there some way to stop the helper::type from being instantiated with 'const char*' in this case? If not, what is a better way to design the helper class to avoid this problem?


Solution

  • If you only want to stop the templated Get method from be instantiated with const char* you could use std::enable_if. That way you could disable the function when T is of type const char*. Here is an implementation of your Get method using std::enable_if:

    template<typename T>
    typename helper<typename std::enable_if<!std::is_same<const char*, T>::value>::type>::type Get(T value) const
    {
        return value;
    }
    

    It is pretty long, but it avoids having to specialize helper<T> for the const char* case. It works by removing the method from overload resolution when T is const char*.

    You can see the documentation for std::is_same here. Both types are in the <type_traits header.