【问题标题】:How to write concepts that make use of ADL如何编写利用 ADL 的概念
【发布时间】:2021-02-07 03:02:25
【问题描述】:

我想写一个概念,让我可以使用 ADL 验证给定语句是否有效并具有正确的返回类型。

在我的具体情况下,我想编写一个 String 概念,它应该强制执行以下要求:

  • 该类型的const 和非const 风格具有beginend 语义:

     // Akin to what this function does for `T` and `T const`
     template< typename T >
     auto test(T& t) {
         using std::begin;
         return begin(t);
     }
    
     // calling test with `T` and `T const` should be valid.
    
  • beginend 的返回类型对于 const 和非 const 风格是一致的,并且它们满足 std::contiguous_iterator 概念。

到目前为止,我使用的 trait 实现如下:

namespace Adl {

using std::begin;

template< typename T >
using HasBeginT = decltype(begin(std::declval< T >()));

}

template< typename T >
using HasBegin = std::experimental::is_detected< Adl::HasBeginT, T >;

但我想直接将此 ADL 用法嵌入到我的约束定义中。

【问题讨论】:

  • 有什么原因你不能只使用contiguous_range

标签: c++ c++20 concept


【解决方案1】:

成语using std::X; X(...); 在 C++20 之后被认为是个坏主意。现在的标准习惯用法是为X 创建一个customization point object。或者在您的情况下,使用现有的自定义点对象:std::ranges::begin

您调用此类自定义点的方式是完整地拼写出来; 在内部,如果提供的类型有这样的调用,它可以进行 ADL 调用(没有 using 任何东西)。

【讨论】:

  • 这对我来说非常有趣和新鲜(因此我的方法看起来很奇怪)。根据您的建议,我的概念的实现如下所示:coliru.stacked-crooked.com/a/431f8c7295825e1b。您有什么改进建议吗?
  • 您将如何编写伪begin 自定义点对象,以便它使用假设的ns::begin 执行和ADL 调用?在命名空间ns 中写入该CPO,并且根本不使用using
  • @Rerito: 旧习语中using std::begin 的目的是将std::begin 的名称带入当前名称查找中,以便没有命名空间的类型仍然可以找到一个(如重载对于 C 数组)。在新的习语中,您可以将这些默认值写为自定义点的部分
  • 我明白了,这就是我看到的std::ranges::begin 的实现,它以C 数组为特色。感谢您的提醒
  • @Rerito 您应该查看标准库已有的概念,因为您正在重新发明它们。你的BeginTypestd::ranges::iterator_t,你的EndTypestd::ranges::sentinel_t,并且这些类型相同是std::ranges::common_range。检查连续性是contiguous_range
猜你喜欢
  • 1970-01-01
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 2020-12-29
相关资源
最近更新 更多