Имя маскирующей структуры - PullRequest
4 голосов
/ 10 июля 2020

Я пытаюсь замаскировать имя структуры следующим образом:

#define cat_val(l, r) l##r
#define name_mask cat_val(exception_, __COUNTER__)

using i_dont_show_in_rtti = struct name_mask
{
// ...
};

void test()
{
    throw i_dont_show_in_rtti{};
}

Это работает, но только индивидуально в файлах. Если я включу файл, который сделал это, я получу конфликт имен (поскольку __COUNTER__ сбрасывается для каждого файла).

Какие у меня другие варианты? Есть ли другой способ изменить имя так, чтобы оно было непонятным, но уникальным, не сделав мой код неоправданно уродливым?

1 Ответ

4 голосов
/ 12 июля 2020

Это возможно сделать в полностью стандартном C ++ 14.

  #include <cstdlib>

  template <std::size_t N>
  constexpr std::size_t ct_hash(const char (&str)[N])
  {
      std::size_t hash = 0;
      for (std::size_t i = 0; i < N; ++i)
          hash = (hash << 7) + (str[i] * str[i]); // just an example
      return hash;
  }

  template <std::size_t ... hashes>
  struct mangled;


  // don't have to use all of these, it's just an example. may use __COUNTER__ instead of __LINE__.
  #define HIDE_STRUCT(S) \
  using S = struct mangled<ct_hash(__FILE__), __LINE__, ct_hash(__DATE__), ct_hash(__TIME__), ct_hash(#S)>; \
  template <> struct mangled<ct_hash(__FILE__), __LINE__, ct_hash(__DATE__), ct_hash(__TIME__), ct_hash(#S)>

  HIDE_STRUCT(foo)
  {
      int a;
  };

  HIDE_STRUCT(bar)
  {
      int a; char b;
  };

  void test()
  {
      throw foo{};
  }

  void test2()
  {
      throw bar{};
  }

Если вас беспокоят возможные коллизии ha sh, вы можете обратимо зашифровать свои строки вместо их хеширования, но для этого могут потребоваться ослабленные параметры шаблона C ++ 20, не относящиеся к типу (чтобы вы могли параметризовать зашифрованную строку). Вам нужно будет написать функцию шифрования во время компиляции.

...