Я написал упрощенную оболочку string_view
для проекта c++ 14, и с MSVC 2017 он запускает static_assert
во время компиляции, но тот же код во время выполнения передает регулярное assert
. Мой вопрос в том, является ли это ошибкой компилятора, проявляется неопределенное поведение или что-то еще?
Здесь дистиллированный код:
#include <cassert> // assert
#include <cstddef> // size_t
class String_View
{
char const* m_data;
std::size_t m_size;
public:
constexpr String_View()
: m_data( nullptr ),
m_size( 0u )
{}
constexpr char const* begin() const noexcept
{ return m_data; }
constexpr char const* end() const noexcept
{ return m_data + m_size; }
};
void static_foo()
{
constexpr String_View sv;
// static_assert( sv.begin() == sv.end() ); // this errors
static_assert( sv.begin() == nullptr );
// static_assert( sv.end() == nullptr ); // this errors
}
void dynamic_foo()
{
String_View const sv;
assert( sv.begin() == sv.end() ); // this compiles & is optimized away
assert( sv.begin() == nullptr );
assert( sv.end() == nullptr ); // this compiles & is optimized away
}
Вот ссылка Компилятора, которую я использовал для репликации проблемы.
Из того, что я могу сказать, добавление или вычитание 0
из любого значения указателя всегда справедливо:
- c++ - Определено ли поведение вычитания двух указателей NULL? - Переполнение стека, последний blockquote
- Аддитивные операторы - cppreference.com, последняя пуля последнего списка пули
- libstd c++: string_view Source File, реализация
end()
и т.д.
Временное решение:
Если я изменю свой метод end
на следующий, static_assert
провал static_assert
.
constexpr char const* end() const noexcept
{ return ( m_data == nullptr
? m_data
: m_data + m_size ); }
Лужение:
Я подумал, что, возможно, выражение m_data + m_size
само по себе является UB, прежде чем m_size == 0
. Тем не менее, если я заменил реализацию end
бессмысленным return m_data + 0;
, это все равно генерирует две ошибки static_assert
. : -/
Обновить:
Это похоже на ошибку компилятора, которая была установлена между 15.7 и 15.8.