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?
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.