Journal Obfusque ton code avec C++

Posté par  (site web personnel) . Licence CC By‑SA.
Étiquettes :
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  (site web personnel) . Évalué à 3.

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

    git is great because linus did it, mercurial is better because he didn't

    • [^] # Re: Sans macro

      Posté par  (site web personnel) . Évalué à 3.

      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.

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

  • # Code pas TapTempo \o/

    Posté par  . Évalué à 10.

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

    ->[]

  • # Pas C++11

    Posté par  (Mastodon) . Évalué à 6.

    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  (site web personnel) . Évalué à 2.

      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 :-)

Suivre le flux des commentaires

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