I have a functor which operates on a container of type U
of elements of type T
like so
template<typename T, template<typename...> class U>
class asserter
{
public:
asserter(U<T> &c) : container(c) { };
void operator()(T lhs)
{
CU_ASSERT(container.find(lhs) != container.end());
};
private:
U<T> &container;
};
which I might use as
std::set<std::string> a, c;
...
asserter<std::string, std::set> ass(c);
for_each(a.begin(), a.end(), ass);
Where we are ignoring std::includes()
for the moment.
This works great if the container is one where U::find()
is defined. If it's not I'd like to fall back to std::find()
. On the other hand I'd rather use U::find()
over std::find()
if it's available.
In C++11 (or 17 if necessary) can I determine if U::find()
is available (possibly restricting to the STL) for U and if so use it, otherwise use std::find()
?
SFINAE on whether the expression c.find(value)
is well-formed. Trailing return type is C++11, and not essential here anyway; it just makes the return type easier to write - decltype(c.find(value))
instead of decltype(std::declval<Container&>().find(std::declval<const T&>()))
.
If the expression would be ill-formed, the first overload of find_impl
is removed from the overload set, leaving the second overload as the only viable one. The usual int/long/0
trick for the third parameter makes the first overload preferred when both are viable.
template<class Container, class T>
auto find_impl(Container& c, const T& value, int) -> decltype(c.find(value)){
return c.find(value);
}
template<class Container, class T>
auto find_impl(Container& c, const T& value, long) -> decltype(std::begin(c)){
return std::find(std::begin(c), std::end(c), value);
}
template<class Container, class T>
auto find(Container& c, const T& value) -> decltype(find_impl(c, value, 0)) {
return find_impl(c, value, 0);
}
The usual disclaimer applies: this relies on expression SFINAE, which is not currently supported by MSVC; Microsoft does plan to add support in an update to MSVC 2015.
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