如何在约束中使用 using 声明

Jar*_*d42 5 c++ using-declaration c++-concepts c++20

是否有其他方法可以using在概念/约束中进行一些声明?就像是:

template <typename T>
concept has_begin_v0 = requires (T t)
{
    using std::begin; // KO
    begin(t);
    /*..*/
};
Run Code Online (Sandbox Code Playgroud)

我发现的可能的方法是:

  • 使用中间体namespace

    namespace detail
    {
    using std::begin;
    template <typename T>
    concept has_begin_v1 = requires (T t)
    {
        begin(t);
    };
    }
    using detail::has_begin_v1;
    
    Run Code Online (Sandbox Code Playgroud)

    引入额外的命名空间:-(

  • 使用 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);
    };
    
    Run Code Online (Sandbox Code Playgroud)

    这不是一个很好的语法。

  • 使用限定调用和 adl 调用的“析取”:

    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>;
    
    Run Code Online (Sandbox Code Playgroud)

    IMO 更好,但似乎无法扩展,也不允许进一步发展(begin(t)与end(t)?)。

演示

Nic*_*las 3

一般来说,你应该避免采取这种using std::begin伎俩。由于您已经在 C++20 中进行操作,因此您可以使用范围自定义点对象std::ranges::begin。它可以通过直接通话完成您所需的 ADL 体操,因此您不需要using std::begin.