С компилятором C ++ 11 с полной поддержкой constexpr
мы можем использовать конструктор constexpr
с использованием функции constexpr
, которая компилируется в неконстантное тело выражения в случае, если предусловие завершающего нулевого символа не является выполнено, что привело к сбою компиляции с ошибкой. Следующий код расширяет код UncleBens и вдохновлен статьей блога Andrzej's C ++ :
#include <cstdlib>
class Literal
{
public:
template <std::size_t N> constexpr
Literal(const char (&str)[N])
: mStr(str),
mLength(checkForTrailingZeroAndGetLength(str[N - 1], N))
{
}
template <std::size_t N> Literal(char (&str)[N]) = delete;
private:
const char* mStr;
std::size_t mLength;
struct Not_a_CString_Exception{};
constexpr static
std::size_t checkForTrailingZeroAndGetLength(char ch, std::size_t sz)
{
return (ch) ? throw Not_a_CString_Exception() : (sz - 1);
}
};
constexpr char broke[] = { 'a', 'b', 'c' };
//constexpr Literal lit = (broke); // causes compile time error
constexpr Literal bla = "bla"; // constructed at compile time
Я тестировал этот код с помощью gcc 4.8.2. Сбой компиляции с MS Visual C ++ 2013 CTP, так как он все еще не полностью поддерживает constexpr
(constexpr
функции-члены по-прежнему не поддерживаются).
Вероятно, я должен упомянуть, что мой первый (и предпочтительный) подход состоял в том, чтобы просто вставить
static_assert(str[N - 1] == '\0', "Not a C string.")
в теле конструктора. Сбой при ошибке компиляции, и кажется, что конструкторы constexpr
должны иметь пустое тело. Я не знаю, является ли это ограничением C ++ 11 и может ли оно быть смягчено будущими стандартами.