I have a class that contains a static constexpr
array of const char
s, which i would like to make available via a c_str()
method:
class my_class {
private:
static constexpr const char c_str_[6] = {'c', 'h', 'a', 'r', 's', '\0'};
public:
static constexpr const char* c_str() {
return c_str_;
}
};
This works, but has an unfortunate effect: It removes the length of the pointed-to array from the type:
decltype(my_class::c_str()) // equivalent to const char*
What I'd really like is some way to achieve this:
decltype(my_class::c_str()) // equivalent to const char[6]
I understand that in either case the returned object will be a pointer; I would just like to preserve the length of the pointed-to array in the type. Kind of like how decltype("string literal")
is const char[15]
, not const char*
.
Is there a way to do this?
You mean like returning a reference to c_str_
?
static constexpr decltype(c_str_)& c_str() { return c_str_; }
or
static constexpr auto& c_str() { return c_str_; }
If you want a pointer, just swap the &
for a *
and return &c_str_
.
If you want to explicitly refer to the type, use an alias:
using T = const char[6];
static constexpr T& c_str() { return c_str_; }
Or if you really hate yourself:
static constexpr const char (&c_str())[6] { return c_str_; }
Note that you cannot have a function return a raw array by value.
A modern alternative would be returning a string_view
, which basically is the combination of a pointer to the string and the length. That allows the user of your function to directly access the length information. And the string could be stored in a null-terminated or non-null-terminated fashion in my_class
.
As far as I can see string_view
supports a constexpr constructor too.
However this doesn't allow for the signature const char* c_str()
. If you are bound to that, the string must be null-terminated in order to allow the caller to retrieve the length (by counting).
Yes there is a way but a small modification is required in your code which is as follows,
#include <iostream>
#include <type_traits>
class my_class {
private:
static constexpr const char c_str_[6] = {'V', 'a', 'a', 'n', 'i', '\0'};
public:
static constexpr auto c_str() -> const char( &)[6] {
return c_str_;
}
};
int main(int , char *[])
{
std::remove_reference< decltype( my_class::c_str())>::type arr = { 'S', 'a', 'a', 'v', 'i', '\0'};
std::cout<< arr<< " is a beautiful name."<< std::endl;
return 0;
}
Output: Saavi is a beautiful name.
Now my_class::c_str()
return reference const char ( &)[6]
. This reference is very special because it can only refer an constant array of char
type which have length 6
and it is different from pointer. Now type information can be retrieve.
So std::remove_reference<>::type
comes to rescue, its type
can point to the type the reference is referring which is const char[6]
.
To verify this, i have created const char
array named arr
which is const char[6]
without specifying length of array.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.