Existe-t-il un moyen d'implémenter les chaînes de caractères pour qu'elles fonctionnent à la fois au moment de la compilation et au moment de l'exécution ?
AFAIK pour qu'une classe soit construite constexpr, elle doit avoir un destructeur trivial. Cependant, cela s'avère difficile lorsqu'il s'agit de chaînes de caractères. Si la chaîne n'est PAS constexpr, elle doit désallouer de la mémoire. Cependant, si elle est constexpr, elle est allouée statiquement et ne doit pas être supprimée, ce qui permet d'avoir un destructeur trivial.
Cependant, il n'est pas possible de dire "Hey, Compiler ! Si je suis constexpr, tu n'as pas besoin de me déstructurer !". Ou bien est-ce le cas ?
Il s'agirait de quelque chose comme ce qui suit :
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); }
}
};
La solution la plus proche que j'ai trouvée est d'avoir deux types distincts, string et constexpr_string, un littéral défini par l'utilisateur _string renvoyant constexpr_string, et une conversion implicite définie par l'utilisateur de constexpr_string vers string.
Ce n'est cependant pas très agréable, car const auto s = "asdf"_string;
fonctionne mais const string s = "asdf"_string;
ne le fait pas. De plus, une référence ou un pointeur vers une chaîne constexpr_string ne sera pas converti. L'héritage, dans un sens ou dans l'autre, provoque des "gotcha" non intuitifs et ne résout pas le premier problème.
Cela semble possible, à condition que le compilateur fasse CONFIANCE au programmeur que le constexpr n'a pas besoin d'être détruit.
Si j'ai une idée fausse, faites-le moi savoir.