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
namespacenamespace 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::begintrick. 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.