当前位置:  开发笔记 > 编程语言 > 正文

std :: begin-类型特征未考虑用户定义的重载

如何解决《std::begin-类型特征未考虑用户定义的重载》经验,为你挑选了1个好方法。

考虑以下类型特征:

template
struct has_begin : std::false_type {};

template
struct has_begin>()))
  >> : std::true_type {};

为什么此特征不考虑我的用户定义的重载std::begin

namespace std {
void begin(foo&) {}
}

int main() {
  static_assert(has_begin::value); // Fails.

  foo f;
  std::begin(f); // Works.
}

现场例子

有趣的观察:

    如果我更改此类型特征的顺序和我的重载,它将起作用

    如果我在特征类型中使用ADL:

decltype(std::begin(std::add_lva... -> decltype(begin(std::add_lva...

如果free函数beginfoo位于相同的名称空间中,则它可以工作:

void begin(foo) {
}

但是对于std ::之外的任何类都失败,具体取决于:

void begin(foo) {
}

因为ADL查找不适用于其他名称空间的模板。


std::begin(foo&)在不更改包含顺序的情况下,我可以做些什么来支持我的类型特征?

否则,我必须同时支持这两个世界-为std :: begin和ADL begin()编写类型特征。

在我的函数中,我已经做了这样的事情(建议在这里):

auto get_begin() {
  using std::begin;
  return begin(object);
}

Nicol Bolas.. 6

在不更改包含顺序的情况下,我该怎么做才能在其类型特征中支持std :: begin(foo&)?

你不 std::begin并不意味着直接为任意范围调用。如果要访问begin/end范围类型,则应结合使用ADL和ADL using std::begin/end。这就是成语在C ++中的工作方式。

重载std名称空间中的方法是非法的,std::begin也不例外。您可以创建std-defined模板的模板专业化(基于用户创建的类型),但这不是使用C ++习惯用法的正确方法。

在C ++ 20中,该std::ranges::begin函数应直接调用,而针对类型专门化该函数的方法是通过ADL或成员begin函数。因此,只要使用该成语,每个人都会没事的。



1> Nicol Bolas..:

在不更改包含顺序的情况下,我该怎么做才能在其类型特征中支持std :: begin(foo&)?

你不 std::begin并不意味着直接为任意范围调用。如果要访问begin/end范围类型,则应结合使用ADL和ADL using std::begin/end。这就是成语在C ++中的工作方式。

重载std名称空间中的方法是非法的,std::begin也不例外。您可以创建std-defined模板的模板专业化(基于用户创建的类型),但这不是使用C ++习惯用法的正确方法。

在C ++ 20中,该std::ranges::begin函数应直接调用,而针对类型专门化该函数的方法是通过ADL或成员begin函数。因此,只要使用该成语,每个人都会没事的。

推荐阅读
重庆制造漫画社
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有