J'en ai créé un aujourd'hui, et testé sur GCC4.6.0.
#include <iostream>
#define E(L,I) \
(I < sizeof(L)) ? L[I] : 0
#define STR(X, L) \
typename Expand<X, \
cstring<E(L,0),E(L,1),E(L,2),E(L,3),E(L,4), E(L,5), \
E(L,6),E(L,7),E(L,8),E(L,9),E(L,10), E(L,11), \
E(L,12),E(L,13),E(L,14),E(L,15),E(L,16), E(L,17)> \
cstring<>, sizeof L-1>::type
#define CSTR(L) STR(cstring, L)
template<char ...C> struct cstring { };
template<template<char...> class P, typename S, typename R, int N>
struct Expand;
template<template<char...> class P, char S1, char ...S, char ...R, int N>
struct Expand<P, cstring<S1, S...>, cstring<R...>, N> :
Expand<P, cstring<S...>, cstring<R..., S1>, N-1>{ };
template<template<char...> class P, char S1, char ...S, char ...R>
struct Expand<P, cstring<S1, S...>, cstring<R...>, 0> {
typedef P<R...> type;
};
Certain test
template<char ...S>
struct Test {
static void print() {
char x[] = { S... };
std::cout << sizeof...(S) << std::endl;
std::cout << x << std::endl;
}
};
template<char ...C>
void process(cstring<C...>) {
/* process C, possibly at compile time */
}
int main() {
typedef STR(Test, "Bonjour tout le monde") type;
type::print();
process(CSTR("Salut les amis")());
}
Ainsi, même si vous n'obtenez pas un 'a', 'b', 'c'
, vous obtenez toujours des chaînes de caractères au moment de la compilation.
1 votes
"abc"
est essentiellement la même chose que'a', 'b', 'c', '\0'
, sauf pour les pointeurs.0 votes
Il était autrefois impossible d'instancier un modèle en C++ en utilisant une chaîne C brute si le modèle était paramétré sur un char*. Est-ce que cela a été corrigé dans C++0x ? Si c'est le cas, je pense avoir une façon de faire cette expansion correctement.
0 votes
@Ignacio: Je sais ça, mais tu ne peux pas écrire
"abc"
pour un argument de modèlechar...
. @templatetypedef: Le modèle n'est pas paramétré surchar*
, c'est un modèle variadique surchar...
0 votes
@Peter Alexander : C'est vrai, vrai... mais ne pourriez-vous pas construire une classe de modèle auxiliaire paramétrée sur un char* qui exporte le tuple, puis créer une macro qui instancie ce modèle auxiliaire, puis extrait le type en tuple de celui-ci ? C'est un peu ce à quoi je pensais.
0 votes
@templatetypedef: Idée intéressante, mais je ne pense pas que vous puissiez extraire le tuple du char* (veuillez me corriger si je me trompe)
0 votes
@Peter Alexander - Je pense que vous pourriez le faire avec suffisamment de couches d'indirection : template class CharTuple {}; Ensuite, créez quelque chose qui l'exporte : template class StringToChars { typedef CharTuple/> type; }; Ensuite, créez un adaptateur pour convertir de CharTuple à votre type : template class Adaptor; template class Adaptor> { typedef Foo type; }; Enfin, assemblez tout : template string> FooWrapper { typedef typename Adaptor::type>::type type; };
0 votes
@Peter Alexander- Ouah! J'ai manqué de caractères. Cette idée a du sens? J'ai dû faire quelque chose de similaire une fois pour construire un modèle de "bind" générique.
0 votes
@templatetypedef: Je comprends ce que vous faites, mais que cache ce mystérieux /* réponse */ code? :-)
0 votes
@Peter Alexander- Voir ci-dessous. :-)
2 votes
En C++0x n3225, la spécification permet également
constexpr char index(char const *x, int n) { return x[n]; }
, je pense. Vous pourriez ensuite direint x[index("\x4\x5", 1)];
pour créer unint[5]
par exemple. C'est la substitution d'invocation de fonction.0 votes
stackoverflow.com/a/15912824/2097780