避免在嵌入式上使用 func(char *) api
Avoiding the func(char *) api on embedded
注:
我大大改变了我的问题以使其更具体,但我会将旧问题保留在 post 的末尾,以防它对任何人有用。
新问题
我正在开发一个嵌入式应用程序,它使用以下类型来表示字符串:
- 字符串文字(默认为空终止)
- std::array
(非空终止)
- std::string_view
我想要一个以统一方式接受所有这些的函数。唯一的问题是,如果输入是字符串文字,我将不得不用 strlen
来计算大小,这在其他两种情况下都不起作用,但如果我使用 size
,它就不会在情况 1 上起作用.
我应该使用这样的变体:std::variant<const char *,std::span<char>>
吗?强迫自己使用 std::visit
会很重吗?那东西甚至可以正确匹配所有不同的字符串表示形式吗?
老问题
免责声明,当我在以下上下文中提到“字符串”时,我不是指 std::string,而是指字母数字系列的抽象方式。
大多数情况下,当我必须在 C++ 中处理字符串时,我会使用 void func(const std::string &);
之类的东西,或者在我没有的嵌入式应用程序中不使用 const 和某些 cases.Now 的引用访问 std::string
并且我尝试使用 std::string_view
问题是 std::string_view
当从非文字构造时有时不会以 null 终止
编辑:我稍微改变了这个问题,因为评论暗示了一些非常有用的提示。
所以即使 y 在下面的例子中有一个大小:
std::array<char,5> x{"aa"} ;
std::string_view y(x.data());
我不能将 y 与基于空终止的 c api 一起使用,例如 printf(%s,y.data())
#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)并且它是可移动的(或廉价可复制的)?
我的 class 的基础类型是什么?与基础类型相比,速度成本是多少?
我认为您正在研究 char*
的两个主要语义和三个细微不同的语义。
是的,它们都指向 char
,但是关于如何确定长度的特定于类型的信息并没有被它携带。即使在 C++ 的古老祖先(不是说 C...)中,指向 char
的指针也不总是相同的。已经有指向终止和非终止字符序列的指针不能混合。
在 C++ 中,存在重载函数的工具,它似乎是您问题的明显解决方案。根据第二个参数中的显式大小信息,您仍然可以仅使用一个(辅助)函数来执行实际工作,从而有效地实现它。
重载在 API 上“可见”的函数,为三种类型使用三个版本。让它以适当的方式确定长度,然后调用单个辅助函数,提供该长度。
注:
我大大改变了我的问题以使其更具体,但我会将旧问题保留在 post 的末尾,以防它对任何人有用。
新问题
我正在开发一个嵌入式应用程序,它使用以下类型来表示字符串:
- 字符串文字(默认为空终止)
- std::array
(非空终止) - std::string_view
我想要一个以统一方式接受所有这些的函数。唯一的问题是,如果输入是字符串文字,我将不得不用 strlen
来计算大小,这在其他两种情况下都不起作用,但如果我使用 size
,它就不会在情况 1 上起作用.
我应该使用这样的变体:std::variant<const char *,std::span<char>>
吗?强迫自己使用 std::visit
会很重吗?那东西甚至可以正确匹配所有不同的字符串表示形式吗?
老问题
免责声明,当我在以下上下文中提到“字符串”时,我不是指 std::string,而是指字母数字系列的抽象方式。
大多数情况下,当我必须在 C++ 中处理字符串时,我会使用 void func(const std::string &);
之类的东西,或者在我没有的嵌入式应用程序中不使用 const 和某些 cases.Now 的引用访问 std::string
并且我尝试使用 std::string_view
问题是 std::string_view
当从非文字构造时有时不会以 null 终止
编辑:我稍微改变了这个问题,因为评论暗示了一些非常有用的提示。
所以即使 y 在下面的例子中有一个大小:
std::array<char,5> x{"aa"} ;
std::string_view y(x.data());
我不能将 y 与基于空终止的 c api 一起使用,例如 printf(%s,y.data())
#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)并且它是可移动的(或廉价可复制的)?
我的 class 的基础类型是什么?与基础类型相比,速度成本是多少?
我认为您正在研究 char*
的两个主要语义和三个细微不同的语义。
是的,它们都指向 char
,但是关于如何确定长度的特定于类型的信息并没有被它携带。即使在 C++ 的古老祖先(不是说 C...)中,指向 char
的指针也不总是相同的。已经有指向终止和非终止字符序列的指针不能混合。
在 C++ 中,存在重载函数的工具,它似乎是您问题的明显解决方案。根据第二个参数中的显式大小信息,您仍然可以仅使用一个(辅助)函数来执行实际工作,从而有效地实现它。
重载在 API 上“可见”的函数,为三种类型使用三个版本。让它以适当的方式确定长度,然后调用单个辅助函数,提供该长度。