Erlend Powell
Erlend Powell

Reputation: 13

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?

Upvotes: 0

Views: 182

Answers (1)

phantom
phantom

Reputation: 3342

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.

Upvotes: 0

Related Questions