Инициализация карты из статического члена данных других классов - PullRequest
0 голосов
/ 02 февраля 2019

У нас есть классы, которые выставляют статический член данных в качестве открытых членов, таких как

class A{
public:
    static const string NAME;
    //Other class specific methods
};

И аналогично классу B и нескольким другим классам.

Если мне нужно создать карту, например

static const map<string, string> versionMap = {{A().NAME, "Aa"},
                                               {B().NAME, "Bb"}
                                              };

Временные объекты классов, создаваемые при создании versionMap, гарантированно ли оно всегда имеет определенное поведение?

Ответы [ 3 ]

0 голосов
/ 03 февраля 2019

Похоже, вы реализуете какой-то механизм отражения с именами классов.Почему бы на самом деле не получить имена классов в качестве имен?

Взгляните на:

Могу ли я получить имена типов C ++ способом constexpr?

принятый там ответ позволяет вам написать get_name<A>() и получить строку (_view), которая является "A".И get_name<B>() будет "B" и так далее.Это может быть полезно в вашем случае, так как:

  1. Нет динамически размещаемых данных.
  2. Нет создания каких-либо объектов (хотя @ jhill515 также дает вам это)
  3. Нет необходимости в статических членах - это может работать с классами, которые вы даже не контролируете!
0 голосов
/ 03 февраля 2019

Гарантируется, что будет работать только

  • карта определена в том же модуле компиляции, где определен статический член (например, A.cpp)
  • карта определена ПОСЛЕопределение члена статических данных

Однако вы играете с огнем ... вместо того, чтобы зависеть от порядка статической инициализации, вероятно, лучше использовать определенную локальную переменную static внутри статическая функция-член ;т.е.

// File A.h

struct A {
    static const std::string& NAME();
};

// File Map.cpp

std::map<std::string, std::string> x{{A::NAME(), "A"}};

// File A.cpp

static const std::string& A::NAME() {
    static std::string x = "A string";
    return x;
}

Этот подход гарантированно сработает, поскольку локальные статические переменные инициализируются при первом использовании (и даже автоматически защищаются от проблем многопоточности в C ++ 11).

0 голосов
/ 03 февраля 2019

Когда вы определяете статический член класса, независимо от того, создан ли этот класс или нет, этот член доступен через память.В этом случае, поскольку они являются открытыми членами, использование самих строк в качестве ключей совершенно допустимо.

При этом ваши статические постоянные члены должны быть инициализированы после определения класса, обычночто-то вроде:

class Foo { static const int foo; };
const int Foo::foo = 42;

Для примера статической карты вы должны иметь в виду, что карта должна быть инициализирована аналогичным образом, если она используется в качестве члена класса.Вот рабочий пример:

// Compiled with g++ --std=c++17 -Wall -Wextra -Werror ConstStaticMapExample.cpp -o ConstStaticMapExample
#include <iostream>
#include <string>
#include <map>

class A
{
public:
  static const std::string NAME;
  //Other class specific methods
};
const std::string A::NAME = "foo";

class B
{
public:
  static const std::string NAME;
  //Other class specific methods
};
const std::string B::NAME = "bar";

class C
{
public:
  static const std::map<std::string, std::string> versionMap;
  // More definitions
};
const std::map<std::string, std::string> C::versionMap = {{A::NAME,"aA"},{B::NAME,"bB"}}; // Reversed for explanation

int main(int,char**)
{
  // local static
  static const std::map<std::string, std::string> versionMap = {{A::NAME,"Aa"},{B::NAME,"Bb"}};
  std::cout << "LOCAL STATIC EXAMPLE:" << std::endl;
  for(auto mpair : versionMap)
  {
    std::cout << "Key: " << mpair.first << "\tVal: " << mpair.second << std::endl;
  }

  // class member static
  std::cout << "CLASS MEMBER STATIC EXAMPLE:" << std::endl;
  for(auto mpair : C::versionMap)
  {
    std::cout << "Key: " << mpair.first << "\tVal: " << mpair.second << std::endl;
  }

  return 0;
}

Гист

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...