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

时间:2018-09-10 03:29:13

标签: c++ c++17 constexpr

我正在尝试构建一个手动放置标签的侵入式探查器。如果可以将这些标记转换为整数,然后在编译时直接将其索引到数据结构中,则profile标记的运行时代码尽可能小(例如,可能将一个整数标识符附加到环形缓冲区中),那将是非常好的。

是否可以在编译时使用[@catList]='items'完全做到这一点?不用说,标签将出现在几个不同的编译单元中。

我发现在C ++ 17中使用constexpr的地址是extern友好的,但是我还没有想到让它执行我想要的方式的方法。

是否有一种方法可以做我想做的事,或者根本不可能吗?我看到的主要障碍是,似乎需要一些编译时状态才能在编译单元之间转移。使用constexpr技巧,您可以完成此操作,但是我不确定正在共享的状态是否对我想做的事情有用。

这是我所谈论的例子:

file1.cpp:

extern

file2.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);
}

int function2() { static constexpr auto token2 = MakeGlobalToken(__PRETTY_FUNCTION__ " at " __FILE__ ": " xstr(__LINE__)); BeginProfile(token2); EndProfile(token2); } 会是什么样?还能写吗? MakeGlobalTokentoken1必须是唯一的。而且,理想情况下,它们将成为某种数据结构的索引。

1 个答案:

答案 0 :(得分:2)

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

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);
}