Ответ 1
С++ 17 имеет inline variables
, см. N4424.
Ключевое слово inline
в С++ позволяет определять функции в заголовках, чтобы компилятор мог либо набросать их, либо оставить только одну копию функции. Это позволяет уменьшить количество единиц компиляции, определяя функции непосредственно в заголовках, с преимуществом часто в несколько раз быстрее время компиляции и, возможно, более быстрое выполнение.
Почему этот шаблон нельзя использовать для переменных пространства имен, тогда как функции в С++ на самом деле являются переменными области пространства имен при просмотре их как специального указателя?
То, что я могу думать, это использовать статическую локальную переменную встроенной функции.
inline std::string& Hello__() { //Edit: Added the &
static std::string hello("Hello");
return hello;
}
#define Hello (Hello__())
Изменить: я хотел бы уточнить свой вопрос, как показано ниже.
Я использую термин "inline" как то, что понимает компилятор. Он позволяет одно и то же определение с тем же именем быть в нескольких единицах компиляции, позволяя определение в заголовке. Основным преимуществом "inline" является не преимущество производительности, поскольку макрофункция будет иметь, а более короткое время компиляции из уменьшенного количества единиц компиляции. Это может быть в несколько раз короче.
У меня появилось решение, позволяющее переменной работать как встроенная функция. Но я все еще нахожусь для лучшего способа сделать это.
Чтобы четко заявить, что я хочу достичь, это определение переменной пространства имен в заголовке, например встроенной функции, чтобы сделать процесс сборки максимально простым и быстрым.
Edit2: Благодарим вас за ссылку в комментарии от dyp. Я только что прочитал предложение, и это именно то, о чем я думаю. Каков текущий статус этого предложения?
Цитата из предложения:
Однако, не редкость желать существования глобально уникальный объект без необходимости выбирать один перевод единица, в которой это можно определить. Как практический вопрос, делая этот выбор обычно требует либо использования нетривиальных макросов препроцессора, отдельно скомпилированные библиотеки или и то, и другое. Однако одна сила С++ это его способность поддерживать разработку библиотек headeronly. В эта вена, отсутствие способности определять встроенную переменную poses значительное ограничение на дизайн библиотеки.
С++ 17 имеет inline variables
, см. N4424.
Вот короткий эксперимент, который я сделал с вашим предложением:
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
Итак, я считаю это неправильным использованием языка, потому что результат компиляции непредсказуем и обычно не то, что вы намеревались это сделать. Если комитет сможет определить поведение, которое предсказуемо, я сам использовал бы эти так называемые "встроенные" переменные.
Фактически переменные могут быть 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
$
Ваша "встроенная переменная" Hello
ведет себя точно так же, как глобальная переменная. Единственное отличие состоит в том, что в дополнение к объявлению в заголовке глобальная переменная также требует определения в одном модуле компиляции, а Hello
не нуждается в этом.
Я думаю, причина отсутствия языковой поддержки для "встроенных переменных" - это просто то, что глобальные переменные по праву считаются злыми. Вы просто не используете их в современном коде. Таким образом, языки не должны добавлять сложность к их синтаксису, чтобы поддерживать что-то, что не использовалось в любом случае.