Search code examples
c++templatessfinaetemplate-argument-deduction

disable template member function if return type is an array


https://www.godbolt.org/z/_4aqsF:

template <typename T> struct Container
{
    template <typename TPred> T find_if(TPred pred);  // the culprit
};

template <typename T> Container<T> MakeContainer(T const &)
{
    return Container<T>();    
}

int main()
{
    auto x = MakeContainer("Hello!");
}

gcc, clang and msvc apparently agree that this cannot compile because find_if would return an array.

(I would have assumed that the member template isn't instantiated since it doesn't get used - apparently, this simplistic view is wrong.)

Why does SFINAE not apply here?

Is there a way to exclude the member template for types where T is not a returnable type?


Solution

  • To use SFINAE on fidn_if you need to use dependent parameters of the function itself, here's a version that SFINAE on non-returnable types:

    template <typename TPred, class U = T, typename std::enable_if<
           std::is_same<T, U>::value
        && !std::is_abstract<U>::value
        && !std::is_function<U>::value
        && !std::is_array<U>::value
        , bool>::type = true>
    U find_if(TPred pred);