Je développe ma propre classe de chaîne de caractères qui possède à la fois une optimisation pour les petites chaînes et un indicateur interne pour savoir si la chaîne est Ascii, UTF8, WTF8 ou une chaîne d'octets. Le constructeur
String(const char*);
peut être utilisé pour construire soit une chaîne Ascii, soit une chaîne UTF8. Il ne devrait être utilisé qu'avec des littéraux tels que :
const String nom_de_famille = "Fayard"
const String prénom = "François"
Le constructeur doit calculer à la fois la longueur de la chaîne et vérifier si elle est Ascii ou UTF8. Par conséquent, j'ai écrit ces fonctions pour qu'elles puissent être évaluées au moment de la compilation.
inline constexpr il::int_t size(const char* s) {
return (*s == '\0') ? 0 : (size(s + 1) + 1);
}
inline constexpr bool isAscii(const char* s) {
return (*s == '\0')
? true
: (((static_cast(*s) & 0x80_uchar) ==
0x00_uchar) && isAscii(s + 1));
}
Le constructeur est écrit de cette manière et est disponible dans les en-têtes pour qu'il puisse être inline.
String(const char* data) {
const int n = size(data);
const bool ascii = isAscii(data);
if (n <= max_small_string) {
...
} else {
data_ = malloc();
...
}
}
Mais je n'arrive pas à faire en sorte que les fonctions size et isAscii soient évaluées au moment de la compilation (j'ai essayé et vérifié l'assembly avec gcc 4.8.5, clang 4.0.1, icpc 17.0.4). Y a-t-il un moyen de le faire?
PS : La solution doit être uniquement en C++11 et compilable avec gcc 4.8.5 et Visual Studio 2015.
3 votes
Eh bien, vous donnez ces fonctions des données runtime, alors comment pensez-vous que le compilateur devrait être capable de les évaluer au moment de la compilation ?
0 votes
Avez-vous essayé de déplacer le reste du code de votre constructeur dans une fonction séparée ?
0 votes
@zett42 : Je ne comprends pas ce que vous voulez dire par données d'exécution. Les fonctions
size("Hello")
etisAscci("François")
sont évaluées au moment de la compilation. Pourquoi ne peuvent-elles pas être évaluées au moment de la compilation dans le constructeur lorsque celui-ci est en ligne ?0 votes
@sbabbi: J'ai essayé d'écrire un constructeur avec la signature
String(bool ascii, const char* data, int n)
et de définirString(const char* data) : String{isAscii(data), data, size(data)} {}
. Mais cela ne fonctionne pas non plus.0 votes
Ne devrait pas les constructeurs être quelque chose comme
template constexpr String(const char(&string_literal)[N]);
pour rendre ces chaînes de caractères constexpr compatibles?0 votes
@Öö Tiib : Je ne veux pas que le constructeur soit constexpr. Je veux juste utiliser une fonction constexpr à l'intérieur qui pourrait être évaluée au moment de la compilation. De toute façon, je pense que le malloc rend impossible que ce constructeur soit constexpr.
1 votes
Les arguments passés au constructeur non-constexpr ne seront pas évalués au moment de la compilation.
0 votes
@ÖöTiib : C'est ce que je crains. Voyez-vous une solution de contournement lorsque la fonction peut être en ligne ? La taille des "petites chaînes" est limitée à 22 octets. Au-delà, il convient d'utiliser un malloc.
0 votes
Le
inline
en C++ ne signifie pas qu'il estconstexpr
. Au contraire,constexpr
concernant une fonction implique qu'elle estinline
.0 votes
@Öö Tiib : Je n'utilise pas d'inline pour ça. Ce n'est même pas utilisé pour l'inlining de nos jours. C'est juste là parce que la fonction est définie dans un fichier
*.h
.0 votes
@Öö Tiib : Votre idée de définir
template constexpr String(const char(&string_literal)[n]);
semble être agréable. Mais le constructeur ne peut êtreconstexpr
que lorsquen <= 22
, ce qui correspond au cas de l'optimisation des petites chaînes de caractères, car je crois que malloc n'est pas autorisé dans les constructeurs constexpr. Comment pourrais-je spécifier cela?