2017-12-31 8 views
14

Warum definiert cppreference type_traits xxx_v Verknüpfungen wie inline constexpr und nicht nur constexpr?Warum definiert cppreference type_traits xxx_v Shortcuts als Inline-Contexpr und nicht nur als Constexpr?

Siehe zum Beispiel is_integral_v:

template< class T > 
inline constexpr bool is_integral_v = is_integral<T>::value; 

Ist das nur eine Frage des Stils, oder gibt es einige Unterschiede im Verhalten? Soweit ich weiß constexpr Variablen sind implizit inline.

Edit: Blick auf den Entwurf des neuesten Standards, es verwendet auch inline constexpr. Die Frage gilt dann tatsächlich für den Standard.

+2

https://stackoverflow.com/a/38043566/2466431 – JVApen

+0

Wir haben genau einen 'Inline'-Code in der Dokumentation unserer Typeigenschaftenattributvorlagen erstellt. 'is_integral_v' ist das nicht. –

Antwort

4

[basic.link] /3.2 gilt für Namen von "a non-inline Variable von nicht-flüchtigen Const-qualifizierten Typ". Eine variable Vorlage ist keine Variable, genauso wie eine Klassenvorlage keine Klasse ist, eine Funktionsvorlage keine Funktion und ein Cookie-Cutter kein Cookie. Diese Regel gilt also nicht für die Variablenvorlage is_integral_v.

Eine Variable Vorlage Spezialisierung ist eine Variable, daher gibt es einige Fragen darüber, ob diese Regel gibt es interne Verknüpfung. Dies ist core issue 1713, deren Richtung besagt, dass die Regel nicht anwendbar ist.

Core Problem 1713 wurde jedoch nicht rechtzeitig für C++ 17 gelöst. So entschied sich LWG dafür, einfach inline über die variablen Vorlagen zu verputzen, nur um sicher zu sein, weil sie auch nicht weh tun.

12

[dcl.constexpr]/9

A constexpr Spezifizierer in einer Objektdeklaration erklärt das Objekt als const.

[basic.link]/3.2

Ein Name Namensraum Umfang aufweist, hat interne Bindung wenn es der Name

-a nicht inline Variable des nichtflüchtigen const qualifizierte ist Typ, der weder explizit extern deklariert ist noch zuvor für eine externe Verknüpfung deklariert wurde

Ohne inline Spezifizierer, hätte is_integral_v interne Verknüpfung. Dies könnte problematisch sein, wenn Sie zwei Zeiger mit demselben Variablennamen vergleichen, die in einer anderen Übersetzungseinheit enthalten sind.


ANMERKUNG: die Inline-Spezifizierer ist redundant mit constexpr nur dann, wenn die Variable eine Klasse statisches Datenelement ist.


ein exemple von leicht Verletzung der one definition rule Nach, dass, wenn is_integral_v wo nicht inline passieren könnte.

bad_type_trait.h

template<class T> 
constexpr auto bad_is_integral_v=std::is_integral<T>::value; 

my_header.h

#include "bad_type_trait.h" 
void f(const bool& x); 

inline void g() 
    { 
    f(bad_is_integral_v<int>); 
    //g ODR use the static variable bad_is_integral_v. 
    //"ODR use" approximate definition is: 
    //  the variable is refered by its memory address. 
    } 

source1.cpp

#include "my_header.h" 
void my_func1(){ 
    g(); //the definition of g in this translation unit. 
    } 

source2.cpp

#include "my_header.h" 
void my_func2(){ 
    g(); //is not the same as the definition of g in this translation unit. 
    } 

In den beiden Übersetzungseinheiten wird die Variable bad_is_integral_v als separate statische Variable instanziiert. Die Inline-Funktion g() ist in diesen beiden Übersetzungseinheiten definiert.Innerhalb der Definition von g() wird die Variable bad_is_integral_v ODR verwendet, daher sind die beiden Definitionen g() unterschiedlich, was eine Verletzung der Definitionsregel darstellt.

+3

Aber du weißt schon. Dies wirft eine weitere interessante Frage auf. Warum in aller Welt würde man die Adresse einer Typeigenschaftskonstante nehmen? – StoryTeller

+3

Oder vielleicht erwartet niemand, dass Leute die Adresse nehmen. Da 'std :: xxx <> :: value' wegen der Tatsache, dass es sich um ein statisches Datenelement handelt, inline ist, wird die' xxx_v'-Version ebenfalls inline gemacht, um sie besser zu spiegeln. Es könnte nur eine Frage der Konsistenz sein. – StoryTeller

+2

@StoryTeller Vielleicht, um es zu einer generischen Funktionsvorlage zu übergeben, die eine Weiterleitungsreferenz verwendet? –

Verwandte Themen