Journal Obfusque ton code avec C++

Posté par (page perso) . Licence CC by-sa
15
16
mar.
2018

Cher Nuit-Nal,

toi qui aime le C++11, tu as peut-être déjà essayé de concaténer des chaînes constantes, suivant ce scénario là :

struct Some {
    static constexpr char Name[] = "Mr Popo";
};

char const *escape() {
    auto dogs = cats("hey, ",  Some::Name, " what's up?");
    return dogs;
}

int main() {
  char const* concat = escape();
  puts(concat);

  return 0;
}

Le problème est donc de concaténer des chaines constantes, à compile time et donc d'obtenir la chaîne concaténée dans le binaire final. Et qu'elle ne soit pas allouée sur la pile, mais bien présente dans les .rodata. Et en C++11 seulement, parce que c'est bien d'avoir 7 ans de retard sur le standard (rime).

La solution que j'ai pondue est affreuse ou élégante suivant le point de vue, mais elle combine variadic macro, variadic template, lamba, constexpr, auto et définition de structure locale.

On notera avec stupéfaction la concision du binaire généré, et avec satisfaction le

 .asciz "hey, Mr Popo what's up?"

Allez, pour le plaisir: https://godbolt.org/g/ZfLCp6

  • # Sans macro

    Posté par (page perso) . Évalué à 3 (+2/-0).

    Bon, déjà l'ensemble est terrible, mais est-ce possible de passer cats en function template ?

    l'azerty est ce que subversion est aux SCMs

    • [^] # Re: Sans macro

      Posté par (page perso) . Évalué à 3 (+1/-0).

      J'aurais bien aimé, mais non, la raison étant que si on passe par une fonction template on aurait un truc du genre

      template<class... Ts>
      auto cats(Ts... args) -> decltype(([]() {
          struct _ {
              char const * strings[sizeof...(args)] = {args...};
              const std::array<unsigned, sizeof...(args)> sizes = make_sizes(args...);
        };
        return strcat_helper<_>();}()))

      (parenthèsage non contractuel).

      Dans ce cas le decltype dépend du type de retour de la lambda, ce qui rentre dans la catégorie lambda expression in unevaluated context et c'est interdit. Mais ça passe en c++14 il me semble (vu que le type de retour est inféré).

  • # Compilation

    Posté par . Évalué à 3 (+2/-0).

    Les compilateurs ne tirent pas trop la gueule avec tous ce genre de choses ?

  • # Code pas TapTempo \o/

    Posté par . Évalué à 10 (+9/-0).

    Où alors c'est le pire portage de TapTempo que j'ai vu jusqu'ici !

    ->[]

  • # Pas C++11

    Posté par . Évalué à 6 (+4/-0).

    Le code n'est pas C++11 mais au moins C++14, puisque std::make_index_sequence a été introduit uniquement en C++14 !

    D'ailleurs, avec GCC, la compilation foire (même avec C++14).

    • [^] # Re: Pas C++11

      Posté par (page perso) . Évalué à 2 (+0/-0).

      Si tu lis bien le code std::make_index_sequence n'est pas utilisé, mais une version naïve est fournie.

      Quant au plantage sous GCC, je le constate aussi, mais je l'attribuerai plutôt à une limitation de GCC :-)

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.