Есть ли способ, чтобы функция constexpr, используемая в заголовочном файле, не входила в глобальную область без дополнительного пространства имен для нее? - PullRequest
1 голос
/ 24 июня 2019

У меня есть файл заголовка с кодом, который выглядит просто так:

constexpr uint32 GenTag(const char tag[5]) { ... }

class SomeClass
{
   static constexpr uint32 TAG1 = GenTag("smth");
   static constexpr uint32 TAG2 = GenTag("abcd");
};
//constexpr needed for switch-case statement

Проблема в том, что функция GenTag() относится к глобальной области видимости, и я хотел бы избежать ее, если это возможно.

Я хотел объявить это внутри класса, но это невозможно с constexpr (объяснение здесь: constexpr не работает, если функция объявлена ​​внутри области действия класса ).

Имеет ли c ++что-нибудь вроде «undeclare» функции в конце заголовка (может быть, некоторые трюки с макросами)?Или какие-то другие варианты я пропустил?Если бы не было лучшего способа, я бы, вероятно, выбрал бы дополнительное (может быть, чрезмерное) пространство имен, но хотел бы спросить, есть ли другие идеи.

Ответы [ 3 ]

3 голосов
/ 24 июня 2019

Нет способа «отменить» функцию или переменную в C ++ (заголовочный файл или нет - файл заголовка просто включен в текущий модуль перевода).Вам нужно будет использовать пространство имен или превратить GenTag в макрос.Вы можете отменить определение макросов с помощью #undef MACRONAME.

2 голосов
/ 24 июня 2019

Как насчет определения GenTag() как static constexpr метода в унаследованной структуре?

Если вы хотите, чтобы GenTag() можно было использовать только внутри SomeClass, вы можете сделать его private и определитьSomeClass как friend внутри класса, содержащего GenTag().

Я имею в виду ... что-то следующее

#include <iostream>

struct SomeClass;

class foo
 {
   static constexpr char GenTag(const char tag[5])
    { return tag[0]; }

   friend SomeClass;
 };

struct SomeClass : public foo
 {
   static constexpr char TAG1 = GenTag("smth");
   static constexpr char TAG2 = GenTag("abcd");
 };

int main()
 {
   std::cout << "Tag1: " << SomeClass::TAG1 << std::endl;
   std::cout << "Tag2: " << SomeClass::TAG2 << std::endl;

   // compilation error: 'GenTag' is a private member of 'foo'
   // static constexpr char TAG3 = foo::GenTag("wxyz");
 }

С трюком friend вам не нужнонаследовать от foo;но без наследования вы должны использовать его как foo::GetTag().

0 голосов
/ 26 июня 2019

Если кто-либо когда-либо столкнется с такой проблемой, я бы порекомендовал вам вообще не использовать такой constexpr в заголовке, а вместо этого объявить-определить его непосредственно в и только в файле cpp. Тогда вы точно избежите ненужного загрязнения окружающей среды.

Или, если есть несколько мест, где такие константы могут использоваться, создайте для них отдельное сообщение без каких-либо классов и включите этот файл отдельно от включения заголовка определения класса.

...