c++templatesc++-conceptsrange-v3

What is this "template(bool Other)( requires ....) classname(...)" syntax in the ranges-v3 library?


I was looking at how concat_view was implemented in ranges-v3 and stumbled upon some seemingly unknown syntax for a templated constructor:

template<bool IsConst>
struct sentinel
{
private:
    friend struct sentinel<!IsConst>;
    friend struct cursor<IsConst>;
    template<typename T>
    using constify_if = meta::const_if_c<IsConst, T>;
    using concat_view_t = constify_if<concat_view>;
    sentinel_t<constify_if<meta::back<meta::list<Rngs...>>>> end_;

public:
    sentinel() = default;
    sentinel(concat_view_t * rng, end_tag)
      : end_(end(std::get<cranges - 1>(rng->rngs_)))
    {}
    //! This here is what I'm asking about:
    template(bool Other)(
        requires IsConst AND CPP_NOT(Other)) //
    sentinel(sentinel<Other> that)
      : end_(std::move(that.end_))
    {}
};

This code can be found here.

The last bit seems to be a template constructor but I've never seen the template(type identifier)(requires ...) syntax before.

What is it and where can I find a description of it?


Solution

  • This is a macro defined at include/range/v3/detail/prologue.hpp:33

    #define template(...)                                                           \
        CPP_PP_IGNORE_CXX2A_COMPAT_BEGIN                                            \
        template<__VA_ARGS__ CPP_TEMPLATE_AUX_                                      \
    

    It translates new C++20 features to pre C++20 SFINAE technique.

    The shown constructor in the question is translated to C++20

    template <bool Other>
      requires IsConst && (!(Other))
    sentinel(sentinel<Other> that) : end_(std::move(that.end_)) {}
    

    or pre C++20

    template <bool Other,
              bool CPP_true = true,
              std::enable_if_t<IsConst && CPP_true, int> = 0,
              std::enable_if_t<(!(Other)) && CPP_true, int> = 0>
    sentinel(sentinel<Other> that) : end_(std::move(that.end_)) {}
    

    requires also seems to be a conditional macro.