是否可以跨多个源文件构建 constexpr 数据结构?



我正在尝试构建一个侵入式分析器,其中标签是手动放置的。如果这些标签可以转换为在编译时直接索引到数据结构的整数,那么配置文件标签的运行时代码尽可能小(例如,可能将整数标识符附加到环形缓冲区(,那就太好了。

是否可以使用constexpr在编译时完全执行此操作?不用说,标签将出现在几个不同的编译单元中。

我发现在 C++17 中获取extern的地址constexpr友好,但我还没有想到一种方法来让它做我想做的事。

有没有办法做我想做的事,还是根本不可能?我看到的主要障碍是,似乎需要一些编译时状态才能在编译单元之间传输。使用extern技巧,您可以完成此操作,但我不确定共享的状态对我想做的事情是否有用。

以下是我所说的一个例子:

文件1.cpp:

#include <ProfilerThing.h>
#define xstr(a) str(a)
#define str(a) $a
int function1()
{
static constexpr auto token1 = MakeGlobalToken(__PRETTY_FUNCTION__ " at " __FILE__ ": " xstr(__LINE__));
BeginProfile(token1);
EndProfile(token1);
}

文件2.cpp:

int function2()
{
static constexpr auto token2 = MakeGlobalToken(__PRETTY_FUNCTION__ " at " __FILE__ ": " xstr(__LINE__));
BeginProfile(token2);
EndProfile(token2);
}

MakeGlobalToken必须是什么样子?甚至可以写吗?token1token2必须是独一无二的。 而且,理想情况下,它们将成为某种数据结构的索引。

首先想到的是地址。它们保证是唯一的,并且易于散列。

template<auto>
struct token
{
inline static struct {} dummy;
};
template<auto x>
constexpr void* MakeGlobalToken()
{
return &token<x>::dummy;
}

用作

inline std::unordered_map<void*, int> logger;
void BeginProfile(void* token)
{
logger[token]++;
}
void EndProfile(void* token)
{
logger[token]++;
}
int function1()
{
static constexpr auto token1 = MakeGlobalToken<function1>();
BeginProfile(token1);
EndProfile(token1);
}
int function2()
{
static constexpr auto token2 = MakeGlobalToken<function2>();
BeginProfile(token2);
EndProfile(token2);
}

最新更新