Почему не встроенные переменные?

Ключевое слово inline в С++ позволяет определять функции в заголовках, чтобы компилятор мог либо набросать их, либо оставить только одну копию функции. Это позволяет уменьшить количество единиц компиляции, определяя функции непосредственно в заголовках, с преимуществом часто в несколько раз быстрее время компиляции и, возможно, более быстрое выполнение.

Почему этот шаблон нельзя использовать для переменных пространства имен, тогда как функции в С++ на самом деле являются переменными области пространства имен при просмотре их как специального указателя?

То, что я могу думать, это использовать статическую локальную переменную встроенной функции.

inline std::string& Hello__() { //Edit: Added the &
    static std::string hello("Hello");
    return hello;
}

#define Hello (Hello__())

Изменить: я хотел бы уточнить свой вопрос, как показано ниже.

Я использую термин "inline" как то, что понимает компилятор. Он позволяет одно и то же определение с тем же именем быть в нескольких единицах компиляции, позволяя определение в заголовке. Основным преимуществом "inline" является не преимущество производительности, поскольку макрофункция будет иметь, а более короткое время компиляции из уменьшенного количества единиц компиляции. Это может быть в несколько раз короче.

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

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


Edit2: Благодарим вас за ссылку в комментарии от dyp. Я только что прочитал предложение, и это именно то, о чем я думаю. Каков текущий статус этого предложения?

Цитата из предложения:

Однако, не редкость желать существования глобально уникальный объект без необходимости выбирать один перевод единица, в которой это можно определить. Как практический вопрос, делая этот выбор обычно требует либо использования нетривиальных макросов препроцессора, отдельно скомпилированные библиотеки или и то, и другое. Однако одна сила С++ это его способность поддерживать разработку библиотек headeronly. В эта вена, отсутствие способности определять встроенную переменную poses значительное ограничение на дизайн библиотеки.

Ответ 1

С++ 17 имеет inline variables, см. N4424.

Ответ 2

Вот короткий эксперимент, который я сделал с вашим предложением:

file a.cpp:

inline int& get_inline_int() {
    static int my_inline_int = 0;
    return my_inline_int;
}

void set_me(int x) {
    get_inline_int() = x;
}

файл b.cpp:

#include <iostream>

inline int& get_inline_int() {
    static int my_inline_int = 0;
    return my_inline_int += 2;
}

void show_me() {
    std::cout << get_inline_int() << std::endl;
}

file main.cpp:

void set_me(int);
void show_me();

int main() {
    set_me(7);
    show_me();
    set_me(8);
    show_me();
    return 0;
}

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

Я должен признать, что результат удивил меня. Я попробовал это как с g++, так и с clang++ и получил аналогичные результаты:

clang++ a.cpp b.cpp main.cpp -o runme

выводит

7
8

clang++ b.cpp a.cpp main.cpp -o runme

выводит

9
10

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

Ответ 3

Фактически переменные могут быть inline d, но они не будут глобально одинаковыми.

zzz.h:

#ifndef ZZZ_H_b6e267bb76401a0cd6502e426a702e41d792a853
#define ZZZ_H_b6e267bb76401a0cd6502e426a702e41d792a853

namespace {
    int omg;
}

static int hello;

// int thisWouldBreakCompilationSoIsCommentedOut;

#endif

xxx.cpp:

#include "zzz.h"

zzz.cpp:

#include "zzz.h"

int main() {}

Посмотрим, компилируется ли он вообще:

$ g++ xxx.cpp zzz.cpp
$

Ответ 4

Ваша "встроенная переменная" Hello ведет себя точно так же, как глобальная переменная. Единственное отличие состоит в том, что в дополнение к объявлению в заголовке глобальная переменная также требует определения в одном модуле компиляции, а Hello не нуждается в этом.

Я думаю, причина отсутствия языковой поддержки для "встроенных переменных" - это просто то, что глобальные переменные по праву считаются злыми. Вы просто не используете их в современном коде. Таким образом, языки не должны добавлять сложность к их синтаксису, чтобы поддерживать что-то, что не использовалось в любом случае.