Partial specialization for a pointer as a function return type

I have a template wrapper function that returns a value similar to this:

template<class T>
T foo(Bar& bar, const char* key) {
    return bar.value<T>(key);
}

But I want it to handle pointer types in a slightly different way, for example:

template<class T>
T foo(Bar& bar, const char* key) {
    return (T)bar.value<void*>(key);
}

So what can I do:

int x = foo<int>(bar, "x");
Baz* b = foo<Baz*>(bar, "b");

Writing it, as above, clearly gives me an error due to several definitions. Is there any other way to do this? I would prefer not to add a cast to every function that uses a pointer.

I tried the following:

template<class T>
T foo(Bar& bar, const char* key) {
    if(std::is_pointer<T>::value)
        return (T)bar.value<void*>(key);
    else
        return bar.value<T>(key);
}

But this does not work either because there are QVariants, and they create an error by simply creating an instance of one of their template functions with an unknown pointer type ( bar.value<T>).

+4
source share
2 answers

, , , T .

namespace detail
{
template<class T>
T foo(Bar& bar, const char* key, std::false_type /*not is_pointer*/) {
    return bar.value<T>(key);
}

template<class T>
T foo(Bar& bar, const char* key, std::true_type /*is_pointer*/) {
    return (T)bar.value<void*>(key);
}
}

template<class T>
T foo(Bar& bar, const char* key) {
    return detail::foo<T>(bar, key, std::is_pointer<T>{});
}
+12

.

, :

  • . .
  • SFINAE.

    template<class T>
    typename std::enable_if<std::is_pointer<T>::value, T>::type
    foo(Bar& bar, const char* key) {return (T)bar.value<void*>(key);}
    
    template<class T>
    typename std::enable_if<!std::is_pointer<T>::value, T>::type
    foo(Bar& bar, const char* key) {return bar.value<T>(key);}
    
+8

All Articles