À l'aide de “constexpr” pour utiliser la chaîne de caractères littérale pour le paramètre de modèle
J'ai écrit un code de jeter const char*
à int
en utilisant constexpr
et donc je peux utiliser un const char*
comme un argument de modèle. Voici le code:
#include <iostream>
class conststr
{
public:
template<std::size_t N>
constexpr conststr(const char(&STR)[N])
:string(STR), size(N-1)
{}
constexpr conststr(const char* STR, std::size_t N)
:string(STR), size(N)
{}
constexpr char operator[](std::size_t n)
{
return n < size ? string[n] : 0;
}
constexpr std::size_t get_size()
{
return size;
}
constexpr const char* get_string()
{
return string;
}
//This method is related with Fowler–Noll–Vo hash function
constexpr unsigned hash(int n=0, unsigned h=2166136261)
{
return n == size ? h : hash(n+1,(h * 16777619) ^ (string[n]));
}
private:
const char* string;
std::size_t size;
};
//output function that requires a compile-time constant, for testing
template<int N> struct OUT
{
OUT() { std::cout << N << '\n'; }
};
int constexpr operator "" _const(const char* str, size_t sz)
{
return conststr(str,sz).hash();
}
int main()
{
OUT<"A dummy string"_const> out;
OUT<"A very long template parameter as a const char*"_const> out2;
}
Dans cet exemple de code, le type de out
est OUT<1494474505>
et le type de out2
est OUT<106227495>
. La magie derrière ce code est conststr::hash()
c'est un constexpr
la récursivité qui utilise FNV fonction de Hachage. Et ainsi, il crée intégrante de hachage pour const char* qui, je l'espère, d'un genre unique.
J'ai quelques questions au sujet de cette méthode:
- Est-ce une approche sécuritaire à utiliser? Ou cela peut-il être un mal à un usage spécifique?
- Pouvez-vous écrire une meilleure fonction de hachage qui crée différentes entier pour chaque chaîne, sans être limité à un nombre de caractères? (dans ma méthode, la durée est assez longue)
- Pouvez-vous écrire un code qui, implicitement, jette
const char*
àint constexpr
viaconststr
et donc nous n'aurons pas besoin esthétiquement laid (et aussi le temps des consommateurs)_const
chaîne définie par l'utilisateur littérale? Par exempleOUT<"String">
juridique (et fonte "Chaîne" en entier).
Toute aide sera appréciée, merci beaucoup.
- Si ma réponse decide à votre question, pouvez la marquer comme acceptée ? Sinon, vous pouvez commenter (encore une fois)!
- Oh, toutes mes excuses, j'oublie toujours de le faire 🙂
Vous devez vous connecter pour publier un commentaire.
Bien que votre méthode est très intéressante, il n'est pas vraiment un moyen de passer un littéral de chaîne comme un argument de modèle. En fait, c'est un générateur de modèle argument fondé sur la chaîne littérale, ce qui n'est pas le même: vous ne pouvez pas récupérer
string
dehashed_string
... Ça va à l'encontre l'intérêt de littéraux de chaîne dans les modèles.MODIFIER : ce qui suit a été droit lorsque la valeur de hachage utilisée est la somme pondérée des lettres, ce qui n'est pas le cas suite à la modification de l'OP.
Autant que je sache, vous ne pouvez pas passer une chaîne de caractères littérale dans un modèle argument carrément dans la norme actuelle. Cependant, vous pouvez "faux" il. Voici ce que j'utilise en général:
Ensuite, je passe le "faux littéral de chaîne" à partir d'un argument de type:
EDIT2: vous avez dit dans les commentaires que vous avez utilisé cette distinction entre plusieurs spécialisations d'un modèle de classe. La méthode que vous avez montré est valide, mais vous pouvez aussi utiliser les tags:
OUT
, mais le résultat dehash()
. Je ne pense pas que vous pouvez transformer cette valeur en chaîne... Donc, vous ne pouvez pas avoirOUT
en sortie de la chaîne de caractères que vous avez écrit entre parenthèses._tag
.Voici le modèle que j'utilise pour le modèle const paramètres de la chaîne.
class F {
static constexpr const char conststr[]= "some const string";
TemplateObject<conststr> instance;
};
voir :
https://stackoverflow.com/a/18031951/782168