有没有办法避免 header 文件中使用的 constexpr 函数在没有额外命名空间的情况下进入全局范围?

Is there a way to avoid constexpr function used in header file from entering global scope without extra namespace for it?

我有一个 header 文件,其代码如下所示:

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() 属于全局范围,我想尽可能避免它。

我想在 class 中声明它,但在 constexpr 中是不可能的(此处解释:constexpr not working if the function is declared inside class scope)。

c++ 在 header 的末尾是否有类似 "undeclare" 的函数(也许是一些宏技巧)?或者我错过的任何其他选择?如果没有更好的方法,我可能会使用额外的(可能是过多的)命名空间,但想问问是否还有其他想法。

无法 "undeclare" C++ 中的函数或变量(头文件与否 -- 头文件仅包含在当前翻译单元中)。您需要使用命名空间,或将 GenTag 设为宏。您可以取消定义宏#undef MACRONAME

如何在继承的结构中将 GenTag() 定义为 static constexpr 方法?

如果您希望 GenTag() 仅在 SomeClass 内可用,您可以将其设为 private 并在 [=] 内将 SomeClass 定义为 friend 30=] 包含 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().

如果有人也遇到这样的问题,我建议您根本不要在 header 中使用此类 constexpr,而是考虑直接在 cpp 文件中且仅在 cpp 文件中使用 declare-define 它。那么你一定会避免不必要的全局范围污染。

或者,如果有多个地方可以使用这些常量,则在没有任何 classes 的情况下单独为它们创建一个单独的文件,并将该文件与包含 class 定义 header 分开.