den folgenden vereinfachten Code Stellen:Passing Literal als const ref Parameter
#include <iostream>
void foo(const int& x) { do_something_with(x); }
int main() { foo(42); return 0; }
(1) Optimizations beiseite, was passiert, wenn 42 zu foo
geben wird?
Bleibt der Compiler 42 irgendwo (auf dem Stapel?) Und übergibt seine Adresse an foo
?
(1a) Gibt es etwas im Standard, das vorschreibt, was in dieser Situation zu tun ist (oder ist es ausschließlich dem Compiler überlassen)?
Nun stelle man etwas anders Code: (wegen ODR)
#include <iostream>
void foo(const int& x) { do_something_with(x); }
struct bar { static constexpr int baz = 42; };
int main() { foo(bar::baz); return 0; }
Es ist nicht verbinden wird, es sei denn, ich int bar::baz;
definieren.
(2) Warum kann der Compiler außer ODR nicht das tun, was er mit 42 oben getan hat?
Eine offensichtliche Art und Weise die Dinge zu vereinfachen ist foo
zu definieren:
void foo(int x) { do_something_with(x); }
Doch was würde man im Falle einer Vorlage tun? ZB:
template<typename T>
void foo(T&& x) { do_something_with(std::forward<T>(x)); }
(3) Gibt es eine elegante Art und Weise foo
zu sagen x
von Wert für primitive Typen zu akzeptieren? Oder muss ich es mit SFINAE oder ähnlichem spezialisieren?
BEARBEITEN: Geändert, was innerhalb foo
passiert, wie es für diese Frage irrelevant ist.
Vielleicht ist der Code für T && generiert und T ist für 42 gleich und es ist einfach ein Wert in einem Register in der Funktion unabhängig davon, wie es an die Funktion übergeben wird? –
Wenn diese Frage über die Implementierung des Compilers, die wirklich nicht definiert ist, als ein consxpr-Wert, kann der Compiler die 42 in Register nur innerhalb des Codes "movl". – Swift