简体   繁体   中英

Can C++ functions return a pointer to an array of known length?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM