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?
SFINAE is not in play because the members of the types produced in your MakeContainer
return point are not examined during SFINAE of MakeContainer
overloads.
SFINAE happens only in an immediate context. Bodies of types and functions are not in-scope and do not cause a subsitution failure.
template <typename T=char[7]> Container<char[7]> MakeContainer(char const (&)[7])
this signature is fine.
Once selected, the Container<char[7]>
is instantiated and its methods parsed.
template <typename TPred> char[7] find_if(TPred pred); // the culprit
there is no TPred
that could cause this find_if
to be a valid method, so your program is ill formed no diagnostic required.
The correct fix is:
template <typename T> struct Container
{
template <typename TPred> T find_if(TPred pred); // the culprit
};
template <class T, std::size_t N> struct Container<T[N]>:
Container<std::array<T,N>>
{
using Container<std::array<T,N>>::Container;
};
of course, Container<std::array<T,N>>
itself needs a very special find_if
and probably constructors. But at least it doesn't break immediately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With