Представьте себе следующий упрощенный код:
#include <iostream>
void foo(const int& x) { do_something_with(x); }
int main() { foo(42); return 0; }
(1) Оптимизация в сторону, что происходит, когда 42 передается на foo
?
Использует ли компилятор 42 где-нибудь (в стеке?) и передает его адрес в foo
?
(1a) Есть ли что-нибудь в стандарте, которое диктует, что должно быть сделано в этой ситуации (или это строго до компилятора)?
Теперь представьте немного другой код:
#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; }
Он не будет связываться, если я не определяю int bar::baz;
(из-за ODR?).
(2) Помимо ODR, почему компилятор не может сделать то, что он сделал с 42 выше?
Очевидным способом упрощения вещей является определение foo
как:
void foo(int x) { do_something_with(x); }
Однако, что бы сделать в случае шаблона? Например:
template<typename T>
void foo(T&& x) { do_something_with(std::forward<T>(x)); }
(3) Есть ли элегантный способ сказать foo
принять x
по значению для примитивных типов? Или мне нужно специализировать его с SFINAE или некоторыми такими?
EDIT: Изменено то, что происходит внутри foo
, поскольку оно не имеет отношения к этому вопросу.