C ++函数是否可以将指针返回指向已知长度的数组?

时间:2019-01-21 03:58:27

标签: c++ c++11 c++14 c++17

我有一个包含static constexpr个数组的const char的类,我想通过一种c_str()方法来使用它:

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_;
    }
};

这有效,但有不幸的效果: 它从类型中删除指向数组的长度:

decltype(my_class::c_str()) // equivalent to const char*

我真正想要的是某种实现此目的的方法:

decltype(my_class::c_str()) // equivalent to const char[6]

我知道,无论哪种情况,返回的对象都是指针。我只想保留类型中指向数组的长度。就像decltype("string literal")const char[15],而不是const char*一样。

有没有办法做到这一点?

3 个答案:

答案 0 :(得分:5)

您是想返回对c_str_的引用吗?

static constexpr decltype(c_str_)& c_str() { return c_str_; }

static constexpr auto& c_str() { return c_str_; }

如果要使用指针,只需将&换成*并返回&c_str_

如果要显式引用类型,请使用别名:

using T = const char[6];
static constexpr T& c_str() { return c_str_; }

或者,如果您真的讨厌自己:

static constexpr const char (&c_str())[6] { return c_str_; }

请注意,您不能让函数按值返回原始数组。

答案 1 :(得分:5)

一种现代的选择是返回string_view,这基本上是指向字符串和长度的指针的组合。这使您的函数的用户可以直接访问长度信息。并且该字符串可以以my_class的形式以空终止或非空终止的方式存储。

据我所见string_view supports a constexpr constructor

但是,这不允许签名const char* c_str()。如果您受此限制,则该字符串必须以空值结尾,以便调用方可以通过计数来检索长度。

答案 2 :(得分:1)

是的,但是有一种方法需要对代码进行一些小的修改,如下所示,

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

输出:Saavi is a beautiful name.

现在my_class::c_str()返回引用const char ( &)[6]。此引用非常特殊,因为它只能引用长度为char的{​​{1}}类型的常量数组,并且不同于指针。现在可以检索类型信息。
因此,6可以挽救了它的std::remove_reference<>::type可以指向引用所引用的类型,即type
为了验证这一点,我创建了名为const char[6]的{​​{1}}数组const char,但未指定数组的长度。