【问题标题】:Is it legit to define std::begin for const char*?为 const char * 定义 std::begin 是否合法?
【发布时间】:2019-03-31 10:10:15
【问题描述】:

我有一个不区分大小写比较字符串的函数,它使用std::lexicographical_compare 和自定义比较器。

但是,我希望能够将stringsstring_viewsconst char* 相互比较,以获得最大的便利和效率。

所以我在想:如果我做一个模板,std::stringbegin/endstd::string_viewbegin/end,... 但 const char* 没有,甚至不是非成员函数的形式。

所以可以像这样定义自己的begin/end重载

namespace std {
    const char * begin(const char* str) { return str; }
    const char * end(const char* str) { return str + strlen(str); }
}

这样我就可以将所有内容与所有内容进行比较

std::lexicographical_compare(std::begin(a), std::end(a), std::begin(b), std::end(b), icomp );

?

如果没有,我还能如何解决我的问题?

【问题讨论】:

  • 你永远不应该把东西放到std命名空间中。请改用您自己的命名空间。
  • 啊,是的,我记得 Bjarne Stroustrup 第一次开始在标准中使用“合法”来谈论定义的行为时的争议。但说真的,您可能应该为您的标题选择一个更具描述性的词。
  • @πάνταῥεῖ 有a few cases可以在namespace std声明。
  • 您可以添加到 std 命名空间的唯一内容是模板特化。
  • @Youda008 只需让函数采用std::string_view。然后它与std::stringstd::string_viewconst char * 或任何提供operator string_view 的类一起工作。

标签: c++ string string-comparison string-view


【解决方案1】:

不,这是不合法的,因为const char * 不是用户定义的类型。

如果 C++ 程序添加声明或 定义到命名空间 std 或命名空间 std 中的命名空间 除非另有规定。程序可以添加模板 仅将任何标准库模板专门化到命名空间 std 如果声明依赖于用户定义的类型并且 专业化满足标准库的要求 原始模板,未明确禁止

[namespace.std/1]

您可以改为在其他命名空间中声明它们,例如 ::

const char * begin(const char* str) { return str; }
const char * end(const char* str) { return str + strlen(str); }

并将它们用于不合格的调用

std::lexicographical_compare(begin(a), end(a), begin(b), end(b), icomp );

此外,在 C++20 中,它会更加严格,只允许程序定义类型的类模板特化

除非另有说明,否则 C++ 程序的行为是未定义的 如果它将声明或定义添加到命名空间 std 或 命名空间std内的命名空间。

除非明确禁止,否则程序可以添加模板 任何标准库类模板到命名空间的特化 std 前提是 (a) 添加的声明至少依赖于一个 程序定义的类型和 (b) 专业化符合标准 原始模板的库要求。

[namespace.std]

【讨论】:

  • std::begin 也不是类模板。请注意,C++20 有一个重大变化,其中也不再允许函数特化:stackoverflow.com/questions/52760580/…
  • 我个人也不会将它们放在全局命名空间中(即使它是允许的)。其他开发人员意外使用的机会很高。我会放入我自己的名称空间并明确其用法。
猜你喜欢
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
  • 2012-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-19
  • 1970-01-01
相关资源
最近更新 更多