Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a C++20 way to detect if a type is an instantiation of a template using just concepts and requires()?

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?

like image 917
mcilloni Avatar asked Sep 02 '25 01:09

mcilloni


1 Answers

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.

like image 143
Jarod42 Avatar answered Sep 05 '25 11:09

Jarod42