I have a template function that I want to enable only for standard containers (or containers compatible with standard containers, which at least provide a begin()
Using void_t, we can just make a type trait for having begin() and end() (and anything else you might want to check for, like typename T::iterator, you can just keep piling expressions on):
template
struct is_std_container : std::false_type { };
template
struct is_std_container().begin()),
decltype(std::declval().end()),
typename T::value_type
>>
: std::true_type { };
And then just SFINAE on that:
template
typename std::enable_if<
is_std_container::value,
typename Container::value_type
>::type
f(const Container& c) { .. }
Also, if you really wanted to verify that begin() gives you back a T::iterator (or at least that they're equality comparable), you can do that too:
void_t<
decltype(begin(std::declval()) == std::declval())
>