Avoiding the func(char *) api on embedded

117 Views Asked by At

Note:
I heavily changed my question to be more specific, but I will keep the old question at end of the post, in case it is useful to anyone.

New Question

I am developing an embedded application which uses the following types to represent strings :

  1. string literals(null terminated by default)
  2. std::array<char,size> (not null terminated)
  3. std::string_view

I would like to have a function that accepts all of them in a uniform way. The only problem is that if the input is a string literal I will have to count the size with strlen that in both other cases doesn't work but if I use size it will not work on case 1.

Should I use a variant like so: std::variant<const char *,std::span<char>> ? Would that be heavy by forcing myself to use std::visit ? Would that thing even match correctly all the different representations of strings?

Old Question

Disclaimer when I refer to "string" in the following context I don't mean an std::string but just an abstract way to say alphanumeric series.

Most of the cases when I have to deal with strings in c++ I use something like void func(const std::string &); or without the const and the reference at some cases.Now on an embedded app I don't have access to std::string and I tried to use std::string_view the problem is that std::string_view when constructed from a non literal sometimes is not null terminated Edit: I changed the question a bit as the comments implied some very helphull hints . So even though y has a size in the example below:

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

I can't use y with a c api like printf(%s,y.data()) that is based on null termination

#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);
}

To summarize:
What can I do to implement a stack allocated string that implicitly gets a static size at its constructors (from null terminated strings,string literals, string_views and std::arrays) and it is movable (or cheap copyable)?
What would be the underlying type of my class? What would be the speed costs in comparison with the underlying type?

1

There are 1 best solutions below

3
On BEST ANSWER

I think that you are looking at two largely and three subtly different semantics of char*.

Yes, all of them point at char but the type-specific info on how to determine the length is not carried by that. Even in the ancient ancestor of C++ (not saying C...) a pointer to char was not always the same. Already there pointers to terminated and non-terminated sequences of characters could not be mixed.

In C++ the tool of overloading a function exists and it seems to be the obvious solution for your problem. You can still implement that efficiently with only one (helper) function doing the actual work, based on an explicit size information in a second parameter.
Overload the function which is "visible" on the API, with three versions for the three types. Have it determine the length in the appropriate way, then call the single helper function, providing that length.