Можно ли построить структуру данных constexpr по нескольким исходным файлам? - PullRequest
0 голосов
/ 10 сентября 2018

Я пытаюсь создать навязчивый профилировщик, в котором теги размещаются вручную. Было бы очень хорошо, если бы эти теги могли быть преобразованы в целые числа, которые непосредственно индексируют в структуру данных во время компиляции, чтобы код времени выполнения для тега профиля был как можно меньше (возможно, добавив целочисленный идентификатор в кольцевой буфер, например).

Можно ли использовать constexpr, чтобы сделать это полностью во время компиляции? Излишне говорить, что теги будут встречаться в нескольких разных единицах компиляции.

Я обнаружил, что взятие адреса extern дружественно constexpr в C ++ 17, но я не придумал, как заставить это делать то, что я хочу.

Есть ли способ сделать то, что я хочу, или это просто невозможно? Основное препятствие, которое я вижу, состоит в том, что кажется, что для передачи между модулями компиляции потребуется некоторое время компиляции. Используя трюк extern, вы можете сделать это, но я не уверен, что разделяемое состояние полезно для того, что я хочу сделать.

Вот пример того, о чем я говорю:

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

file2.cpp:

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

    EndProfile(token2);
}

Как должен выглядеть MakeGlobalToken? Можно ли вообще написать? token1 и token2 должны быть уникальными. И в идеале это были бы индексы в какой-то структуре данных.

1 Ответ

0 голосов
/ 10 сентября 2018

Первое, что приходит на ум, это адреса. Они гарантированно уникальны и легко моются.

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