4 votes

Existe-t-il un moyen de transformer une ressource textuelle en une chaîne littérale brute à l'aide du préprocesseur ?

Je viens de remarquer qu'une réponse que j'ai donnée pour cette question en fait, ça ne marche pas :

Que vous utilisiez CMake ou non, ce qui suit devrait fonctionner avec la norme actuelle :

std::string resource = R"(
#include "text.txt"
)";

Je pensais que le pré-processeur reconnaîtrait le format #include "text.txt" en premier lieu et développer le texte.

Mais ce n'est manifestement pas le cas, le résultat pour

std::cout << resource << std::endl;

est

#include "text.txt"

J'ai essayé d'utiliser une macro pour que le #include La déclaration peut être étendue à l'intérieur, mais cela ne fonctionne pas non plus :

#include <string>
#include <iostream>

#define RESOURCE_DEFINIION(resource_var,resource_name) \
    const std::string resource_var = R"xxx( \
    #include resource_name \
    )xxx";

RESOURCE_DEFINIION(resource,"text.txt")

int main()
{
   std::cout << resource << std::endl; 

   return 0;
}

Le résultat est

\                                                                                                                                                                                          
    #include resource_name \                                                                                                                                                                

Voici la démo pour jouer avec


Existe-t-il une astuce permettant de faire entrer le text.txt en une chaîne littérale brute c++-11, en utilisant le préprocesseur ou toute autre fonctionnalité habituelle du langage c++ ?


Avis de non-responsabilité :

Je sais très bien ce qui ne va pas avec les échantillons ci-dessus et pourquoi ils échouent de cette façon. Le problème, c'est que le préprocesseur ignore les éléments qui apparaissent à l'intérieur de " paires.

Existe-t-il un moyen d'échapper à ces derniers pour qu'ils soient vus par le pré-processeur ?

4voto

Revolver_Ocelot Points 4502

Il semble que ce ne soit pas possible en C++ standard

Problème 0 : Le seul moyen standard d'inclusion textuelle est #include directive.

Problème 1 : String literal est un jeton de prétraitement, qui sont reconnus en phase 3, donc lorsque les directives de prétraitement sont exécutées en phase 4, il est déjà déterminé que #include est une partie de la chaîne littérale et non une directive de prétraitement.

preprocessing-token :
    nom de l'en-tête
    identifiant
    numéro de pp
    caractère-littéral
    Caractère-littéral défini par l'utilisateur
    chaîne-littérale
    chaîne-littérale définie par l'utilisateur
    prétraitement-op-or-punc
    chaque caractère non blanc qui ne peut pas être un des caractères ci-dessus

Problème 2 : Il est impossible d'apporter une directive de prétraitement dans le source et de l'exécuter par substitution de macro :

16.3.4/3
La séquence d'expressions de prétraitement entièrement remplacée par des macros qui en résulte n'est pas traitée comme une directive de prétraitement, même si elle y ressemble.

Donc vous ne pouvez pas avoir de travail #include dans la macro.

Problème 3 La liste de remplacement des macros doit être un jeton de prétraitement valide :

ligne de contrôle :
     # définir l'identifiant replacement-list new-line
liste de remplacement :
         pp-tokens opt
pp-tokens :
     pré-traitement des tokens
     pp-tokens preprocessing-token

Et la chaîne littérale est un jeton de prétraitement en soi, vous ne pouvez pas construire une chaîne littérale à partir de plusieurs macros.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X