Is there an alternative to have some using
-declarations in concept/constraint? Something like:
template <typename T>
concept has_begin_v0 = requires (T t)
{
using std::begin; // KO
begin(t);
/*..*/
};
The possible ways I have found are:
use intermediate
namespace
namespace detail { using std::begin; template <typename T> concept has_begin_v1 = requires (T t) { begin(t); }; } using detail::has_begin_v1;
Introduces extra namespace :-(
using SFINAEd lambda:
template <typename T> concept has_begin_v2 = requires (T t) { [](){ using std::begin; return [](auto&& inner) -> std::void_t<decltype(begin(inner))> {}; }()(t); };
Not a fine syntax.
use "disjunction" of qualified call and adl call:
template <typename T> concept has_std_begin = requires (T t) { std::begin(t); }; template <typename T> concept has_adl_begin = requires (T t) { begin(t); }; template <typename T> concept has_begin_v3 = has_std_begin<T> || has_adl_begin<T>;
The nicer IMO, but seems not to scale nor allow to go further (is
begin(t)
comparable withend(t)
?).
You should generally avoid having to do the
using std::begin
trick. Since you're already operating in C++20, you can use the ranges customization point objectstd::ranges::begin
. It does the ADL gymnastics you need on a direct call, so you don't needusing std::begin
.