For many years, I always used the following piece of code to detect if an arbitrary type is a template instantiation:
namespace priv {
template <typename, template <typename...> typename>
struct _is_instance_impl : public std::false_type {};
template <template <typename...> typename U, typename...Ts>
struct _is_instance_impl<U<Ts...>, U> : public std::true_type {};
}
template <typename T, template <typename ...> typename U>
using is_instance = priv::_is_instance_impl<std::decay_t<T>, U>;
This also works fine with C++20 concepts:
template <typename T, template <typename ...> typename U>
concept instance_of = priv::_is_instance_impl<std::decay_t<T>, U>::value;
template <typename T>
std::size_t len_of(T &&s) requires instance_of<T, std::basic_string> {
return s.length();
}
I have attempted to replace this SFINAE-based code with a C++20 requires()
expression, without luck.
Has anyone any idea on how this could be accomplished, if it is actually possible at all?
Without helper, the closest I succeed to get is:
template <class T, template <typename...> class C>
concept test = requires (T t)
{
{[] <typename... Ts>(C<Ts...>& c) -> C<Ts...>& { return c; }(t)} -> std::same_as<T&>;
// simplified version, but allows conversion
//[] <typename... Ts>(C<Ts...>&) {}(t);
};
Demo which is not accepted by clang though.
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