Есть ли способ реализовать строки так, чтобы они работали как во время компиляции, так и во время выполнения?
Насколько я знаю, для построения класса constexpr требуется тривиальный деструктор. Однако это оказывается трудным, когда мы имеем дело со строками. Если строка НЕ является constexpr, то ей необходимо освободить память. Однако, если это constexpr, то он размещается статически и не должен удаляться, что позволяет использовать тривиальный деструктор.
Однако невозможно сказать: «Эй, компилятор! Если я constexpr, тебе не нужно меня уничтожать!» Либо это?
Это будет что-то вроде следующего:
class string {
private:
char * str;
public:
template<std::size_t l>
constexpr string(const char (&s)[l]) : str(&(s[0])) {}
string(const char * s) { str = strdup(s); }
static if (object_is_constexpr) {
~string() = default;
}
else {
~string() { free(str); }
}
};
Самое близкое, что я смог сделать, это иметь два отдельных типа, string и constexpr _string, определяемый пользователем -литерал _string, возвращающий constexpr _и определяемое пользователем -неявное преобразование строки constexpr _в строку.
Это не очень хорошо, так как const auto s = "asdf"_string;
работает, а const string s = "asdf"_string;
нет. Кроме того, ссылка/указатель на строку constexpr _не будет преобразована. Наследование в любом случае приводит к -интуитивным ошибкам и не решает первую проблему.
Это кажется возможным, если компилятор ДОВЕРЯЕТ программисту, что constexpr не нужно уничтожать.
Если у меня есть неправильное представление, дайте мне знать.