stałe globalne constexpr w pliku nagłówkowym i odr
Niestety, jestem nieco zdezorientowany constexpr
, stałymi globalnymi zadeklarowanymi w plikach nagłówkowych i odr.
W skrócie: czy możemy stąd wywnioskować
Https://isocpp.org/files/papers/n4147.pdf
Że
constexpr MyClass const MyClassObj () { return MyClass {}; }
constexpr char const * Hello () { return "Hello"; }
Jest lepsze niż
constexpr MyClass const kMyClassObj = MyClass {};
constexpr char const * kHello = "Hello";
Do definiowania globali w pliku nagłówkowym jeśli chcę" po prostu użyć " tych globalnie zadeklarowanych/zdefiniowanych Bytów i nie chcę myśleć o Jak ich używam?
1 answers
Uwaga: począwszy od C++17, możesz zadeklarować swoje zmienne jako inline.
TL; DR: jeśli chcesz być po (bardzo) bezpiecznej stronie, skorzystaj z funkcji constexpr. Nie jest to jednak z natury konieczne i na pewno nie będzie, jeśli wykonujesz trywialne operacje na tych obiektach i jesteś wyłącznie zainteresowany ich wartością, lub po prostu nie używaj ich w niebezpiecznych scenariuszach wymienionych poniżej.
Podstawowym problemem jest to, że const
zmienne w przestrzeni nazw takie jak twoje (ogólnie) mają wewnętrzne powiązania ([podstawowe.link]/(3.2)). Oznacza to, że każda jednostka tłumaczenia kompilująca odpowiedni nagłówek będzie obserwować inną jednostkę (tj. symbol).
Teraz wyobraź sobie, że mamy szablon lub funkcję inline w nagłówku, używając tych obiektów. ODR jest bardzo precyzyjny w tym scenariuszu- [basic.def.odr]/6:
"inicjowane wyrażeniem stałym" jest z pewnością spotkałam się, skoro rozmawiamy constexpr
. Tak jest " obiekt ma taką samą wartość we wszystkich definicjach D
" jeśli się nie zamilkniesz.
"obiekt nie jest odr-używany" jest prawdopodobnie jedynym wątpliwym warunkiem. Zasadniczo wymaga to, aby nie wymagać istnienia zmiennych runtime jako symbolu, co z kolei implikuje, że
Nie przywiązujesz go do referencji (=>Nie przesyłasz go!)
Ty nie (ani jawnie ani w sposób dorozumiany) przyjąć jego adres.
Jedynym wyjątkiem od drugiej reguły są tablice, które mogą być brane pod adres niejawnie wewnątrz operacji indeksu dolnego, o ile dwie powyższe reguły nie zostaną naruszone dla otrzymanej wartości glvalue.
Dokładniej, ODR-use jest regulowany przez [basic.def.odr]/3:
Zmienna
x
, której nazwa pojawia się jako potencjalnie oceniane wyrażenieex
, jest odr-używana przezex
, chyba że na konwersja lvalue-to-rvalue (4.1) nax
daje wyrażenie stałe (5.20), które nie wywołuje żadnych nietrywialnych funkcji i jeślix
jest obiektem,ex
jest elementem zbioru potencjalnych wyników wyrażeniae
, gdzie albo konwersja lvalue-to-rvalue (4.1) jest zastosowana doe
, alboe
jest wyrażeniem odrzuconej wartości (Klauzula 5).
Zastosowanie l-t-R do dowolnej zmiennej constexpr
zachowa się zgodnie z wymaganiami pierwszej części. Druga część wymaga, aby zmienna może być używana jako wartość , a nie rzeczywisty obiekt ; to znaczy, że jest ostatecznie odrzucana lub bezpośrednio oceniana, biorąc pod uwagę powyższe zasady.
Jeśli unikniesz odr-użycia zmiennej wewnątrz funkcji wbudowanych, szablonów lub tym podobnych, jesteś w porządku. Ale jeśli użyjesz wartości zwracanej przez odpowiednią funkcję constexpr, nie będziesz musiał się martwić, ponieważ wartości PR zachowują się już bardziej jak wartości/literały (Nie obiekty), a funkcje constexpr są wbudowane i na pewno nie będzie naruszać ODR (jeśli nie używasz zmiennych constexpr
wewnątrz!).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-03 12:10:11