Могут ли функции C ++ возвращать указатель на массив известной длины? - PullRequest
0 голосов
/ 21 января 2019

У меня есть класс, который содержит static constexpr массив const char s, который я хотел бы сделать доступным с помощью метода 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 голосов
/ 21 января 2019

Современная альтернатива будет возвращать string_view, который в основном является комбинацией указателя на строку и длину.Это позволяет пользователю вашей функции напрямую получать доступ к информации о длине.И строка может храниться с нулевым или нулевым символом в my_class.

Насколько я вижу, string_view также поддерживает конструктор constexpr .

Однако это не позволяет подписи const char* c_str().Если вы связаны с этим, строка должна заканчиваться нулем, чтобы позволить вызывающей стороне получить длину (путем подсчета).

0 голосов
/ 05 июня 2019

Да, есть способ, но в вашем коде требуется небольшая модификация:

#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, имеющий длину 6 и отличающийся от указателя.Теперь информацию о типе можно получить.Таким образом, std::remove_reference<>::type приходит на помощь, его type может указывать на тип, на который ссылается ссылка, который является const char[6].Чтобы убедиться в этом, я создал массив const char с именем arr, равный const char[6] без указания длины массива.

0 голосов
/ 21 января 2019

Вы имеете в виду возвращение ссылки на 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_; }

Обратите внимание, что функция не может возвращать необработанный массив по значению.

...