it-swarm.com.de

Bedeutet constexpr Inline?

Betrachten Sie die folgende inline Funktion:

// Inline specifier version
#include<iostream>
#include<cstdlib>

inline int f(const int x);

inline int f(const int x)
{
    return 2*x;
}

int main(int argc, char* argv[])
{
    return f(std::atoi(argv[1]));
}

und die entsprechende Version von constexpr:

// Constexpr specifier version
#include<iostream>
#include<cstdlib>

constexpr int f(const int x);

constexpr int f(const int x)
{
    return 2*x;
}

int main(int argc, char* argv[])
{
    return f(std::atoi(argv[1]));
}

Meine Frage lautet: Bedeutet der constexpr -Spezifizierer den inline -Spezifizierer in dem Sinne, dass der Compiler bei Übergabe eines nicht konstanten Arguments an eine constexpr -Funktion versucht, inline die Funktion, als ob der Bezeichner inline in seine Deklaration aufgenommen wurde?

Garantiert der C++ 11-Standard das?

82
Vincent

Ja ([dcl.constexpr], §7.1.5/2 im C++ 11-Standard): "constexpr-Funktionen und constexpr-Konstruktoren sind implizit inline (7.1.2)."

Beachten Sie jedoch, dass der inline -Spezifizierer tatsächlich sehr wenig (wenn überhaupt) Einfluss darauf hat, ob ein Compiler wahrscheinlich eine Funktion inline erweitert oder nicht. Dies wirkt sich jedoch auf die eine Definitionsregel aus, und aus dieser Perspektive muss der Compiler dieselben Regeln für eine constexpr -Funktion wie für eine inline -Funktion befolgen.

Ich sollte auch hinzufügen, dass die Regeln für constexpr -Funktionen in C++ 11, unabhängig davon, ob inline impliziert constexpr, einfach genug waren, dass sie häufig gute Kandidaten für Inline-Funktionen waren Expansion (die wichtigste Ausnahme sind rekursive). Seitdem haben sich die Regeln jedoch zunehmend gelockert, sodass constexpr auf wesentlich größere, komplexere Funktionen angewendet werden kann.

122
Jerry Coffin

constexpr impliziert nicht inline für Variablen (C++ 17-Inline-Variablen)

Während constexprinline für Funktionen impliziert, hat dies unter Berücksichtigung von C++ 17-Inline-Variablen keine Auswirkungen auf Variablen.

Wenn Sie zum Beispiel das minimale Beispiel nehmen, das ich unter folgender Adresse gepostet habe: Wie funktionieren Inline-Variablen? und das inline entfernen, wobei nur constexpr übrig bleibt, wird die Variable multipliziert adressen, die hauptsache inline variablen meiden.

Minimales Beispiel, dass constexprinline für Funktionen impliziert

Wie bereits erwähnt unter: https://stackoverflow.com/a/14391320/895245 Die Hauptwirkung von inline besteht nicht darin, mehrere Definitionen einer Funktion zuzulassen, sondern in einem Standardzitat unter : Wie kann eine C++ - Headerdatei die Implementierung enthalten?

Wir können das beobachten, indem wir mit dem folgenden Beispiel spielen:

main.cpp

#include <cassert>

#include "notmain.hpp"

int main() {
    assert(shared_func() == notmain_func());
}

notmain.hpp

#ifndef NOTMAIN_HPP
#define NOTMAIN_HPP

inline int shared_func() { return 42; }
int notmain_func();

#endif

notmain.cpp

#include "notmain.hpp"

int notmain_func() {
    return shared_func();
}

Kompilieren und ausführen:

g++ -c -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'notmain.o' 'notmain.cpp' 
g++ -c -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'main.o' 'main.cpp' 
g++ -ggdb3  -O0 -Wall -Wextra -std=c++11 -pedantic-errors  -o 'main.out' notmain.o main.o
./main.out

Wenn wir inline aus shared_func Entfernen, schlägt die Verknüpfung fehl mit:

multiple definition of `shared_func()'

weil der Header in mehrere .cpp - Dateien eingeschlossen wird.

Aber wenn wir inline durch constexpr ersetzen, funktioniert es wieder, weil constexpr auch inline impliziert.

GCC implementiert dies, indem die Symbole in den ELF-Objektdateien als schwach markiert werden: Wie kann eine C++ - Headerdatei die Implementierung einschließen?

Getestet in GCC 8.3.0.