【问题标题】:Avoiding the func(char *) api on embedded避免在嵌入式上使用 func(char *) api
【发布时间】:2021-03-14 11:21:29
【问题描述】:

注意:
我对我的问题进行了重大更改,使其更具体,但我会将旧问题保留在帖子末尾,以防它对任何人有用。

新问题

我正在开发一个嵌入式应用程序,它使用以下类型来表示字符串:

  1. 字符串字面量(默认为空终止)
  2. std::array(非空终止)
  3. std::string_view

我想要一个以统一方式接受所有这些的函数。唯一的问题是,如果输入是字符串文字,我将不得不用 strlen 计算大小,这在其他两种情况下都不起作用,但如果我使用 size,它在案例 1 中不起作用。

我应该使用这样的变体:std::variant<const char *,std::span<char>> 吗?强迫自己使用 std::visit 会很重吗?那东西甚至能正确匹配所有不同的字符串表示吗?

老问题

当我在以下上下文中提到“字符串”时的免责声明,我并不是指 std::string,而只是表示字母数字系列的一种抽象方式。

大多数情况下,当我必须在 c++ 中处理字符串时,我会使用 void func(const std::string &); 之类的东西,或者在某些情况下不使用 const 和引用。现在在嵌入式应用程序上,我无法访问 std::string 和我尝试使用std::string_view 问题是std::string_view 从非文字构造时有时不是空终止 编辑:我稍微改变了这个问题,因为 cmets 暗示了一些非常有帮助的提示。 因此,即使 y 在下面的示例中具有大小:

std::array<char,5> x{"aa"} ;
std::string_view  y(x.data());

我不能将 y 与像 printf(%s,y.data()) 这样基于空终止的 c api 一起使用

#include <array>
#include <string_view>
#include "stdio.h"
int main(){
    std::array<char,5> x{"aaa"};
    std::string_view y(x.data());
    printf("%s",x);
}

总结一下:
我能做些什么来实现一个堆栈分配的字符串,它在其构造函数中隐式地获取一个静态大小(来自空终止的字符串、字符串文字、string_views 和 std::arrays)并且它是可移动的(或廉价的可复制的)?
我的班级的基本类型是什么?与底层类型相比,速度成本是多少?

【问题讨论】:

  • std::array&lt;char,5&gt; x{"aa"} ;std::string_view(x.data()); 有什么问题? It works fine here
  • 理解英文描述的代码非常困难。此外,由于您还不知道解决方案,您的描述很可能无法解释对问题至关重要的部分。您能否展示一个 minimal reproducible example 来突出显示您在使用 std::array&lt;char,5&gt; x{"aa"} ;std::string_view(x.data()); 时遇到的任何问题?
  • 我无法理解您所说的可移动是什么意思? std:: string_view 顾名思义;抽象字符串的 const 视图。作为一种观点,它是可复制的。 std::span 可以用作可变的替代方案 - 但作为查看原始字符串的参考。但是底层字符串的深层副本不能通过自动存储进行。在嵌入式系统上,您可以使用 std::basic_string 和自定义分配器 - 而不是 std::string
  • string_view 有一个构造函数,它接受一个指针和一个大小。
  • 这是否明确表示不要为列表中的三种情况中的每一种情况重载您的函数?否则,这似乎是显而易见的解决方案。

标签: c++ c++17 null-terminated string-view


【解决方案1】:

我认为您正在研究char* 的两个主要和三个微妙不同的语义。

是的,它们都指向char,但是关于如何确定长度的特定于类型的信息并没有被它携带。即使在 C++ 的古老祖先(不是说 C...)中,指向 char 的指针也不总是相同的。已经有指向终止和非终止字符序列的指针不能混合。

在 C++ 中存在重载函数的工具,它似乎是解决问题的明显方法。您仍然可以根据第二个参数中的显式大小信息,只使用一个(辅助)函数来有效地实现这一点。
重载API上“可见”的函数,三种类型的三个版本。让它以适当的方式确定长度,然后调用单个辅助函数,提供该长度。

【讨论】:

  • 它是如此简单,我喜欢它。如果我有很多需要 3 个重载的函数会发生什么,我可以避免膨胀吗?还有 std::span 的两个重载呢?
  • 我的荣幸。实际上,我期望必须添加代码详细信息。现在看来你只是忽略了一些你已经熟悉的东西。发生在每个人身上。玩得开心。
  • 我认为可能有一些政策/特征。但这超出了我的专业知识。一件事当然是在三个辅助函数中确定大小。这至少减少了重复代码。
猜你喜欢
  • 1970-01-01
  • 2012-11-01
  • 2018-11-05
  • 1970-01-01
  • 2016-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-06
相关资源
最近更新 更多