Безопасное преобразование в const char * - временная проблема на всю жизнь - PullRequest
0 голосов
/ 23 ноября 2010

У меня есть следующий шаблон, определенный для того, чтобы я мог выполнять явное, но безопасное приведение:

/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}

Часто (например, при передаче аргументов в sprintf и аналогичные функции) я хотел бы использовать этот шаблон длявыполнить преобразование из строкового класса в строку в стиле c.Однако это показывает, что это невозможно при передаче временного значения, поскольку временное не будет существовать достаточно долго.

Рассмотрим следующий пример:

class Object
{
  public:
  MyStringClass GetDebugName() const;
};

Object obj;
printf("%s",safe_cast<const char *>(obj.GetDebugName()));

Временный объект из obj.GetDebugName () lifeтолько во время safe_cast и указатель недействителен (указывает на данные строки, которая уже была уничтожена), когда находится внутри printf.

В качестве обходного пути я в настоящее время использую прямое приведение без вызова шаблона:const char *c = (const char *)(obj.GetDebugName(), но это имеет недостаток, заключающийся в снижении безопасности типов, так как приведение является чрезмерно сильным (например, оно молча преуспеет, даже если obj.GetDebugName () будет возвращать int вместо строкового значения).static_cast может быть немного лучше, но даже если это слишком сильно, я хотел бы получить ошибку в любой ситуации, когда приведение не обязательно будет безопасным.

1) Если я не ошибаюсь, стандартговорит, что временное время жизни - это утверждение (если оно не расширено привязкой к константной ссылке, в этом случае это время жизни ссылки).Глядя на приведенный выше пример printf, я не совсем уверен, что такое «утверждение», и соответствует ли поведение, которое я видел, или нет.Если оператор является целым printf, время жизни const From & from короче - какое время жизни я должен ожидать от временного?Кто-то может уточнить?

2) Есть ли другой способ сделать преобразование, которое было бы безопасным, но результат мог бы прожить достаточно долго, чтобы быть полезным?

Редактировать:

Пожалуйста, рассмотрите это скорее как общий вопрос, я ищу механизм, как можно сделать подобное преобразование в отношении временного времени жизни, меня не очень интересует особый случай какого-либо конкретного строкового класса.

Чтобы прояснить, почему я не хочу использовать .c_str или аналогичную функцию-член: я хотел бы, чтобы код преобразования был независимым от типа, я не хочу, чтобы код полагался на факт, что я знаю эту конкретную строкуТип реализован c_str, я хочу, чтобы он работал, даже если ObjectDebugName вернет другой класс строки, или даже если ObjectDebugName уже возвращает const char * (что исключает возможность вызова .operator const char * ().

Ответы [ 3 ]

2 голосов
/ 23 ноября 2010

Я могу выполнить явное, но безопасное приведение

Я бы назвал это неявным приведением, выполненным явно, или просто и неявным приведением.

1) Если я не ошибаюсь, стандарт гласит, что временное время жизни - это утверждение (если оно не продлено привязкой к константной ссылке, в этом случае это время жизни ссылки).Глядя на приведенный выше пример printf, я не совсем уверен, что такое «утверждение», и соответствует ли поведение, которое я видел, или нет.Если оператор является целым printf, время жизни const From & from короче - какое время жизни я должен ожидать от временного?Кто-нибудь может уточнить?

Вы правы, временный уничтожен после printf уже возвращен.Код, который вы предоставили, должен работать.Если это не так, значит, вы неправильно предоставили важную информацию.

1 голос
/ 23 ноября 2010

Я не знаю, почему вы используете свой собственный класс строк здесь.Есть ли в классе функция-член для извлечения const char * из него?

std :: string GetDebugName ();

printf ("% s", GetDebugName (). C_str ());

будет безопасным, поскольку временное значение останется действительным, например, во время этого оператора.

0 голосов
/ 23 ноября 2010

Вы можете вызвать функцию преобразования напрямую:

printf("%s", obj.GetDebugName().operator const char*());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...