【发布时间】:2018-01-20 13:32:32
【问题描述】:
想象一下下面的简化代码:
#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 或类似的东西专门化它?
编辑:修改了foo内部发生的事情,因为它与这个问题无关。
【问题讨论】:
-
也许为 T&& 和 T 生成的代码对于 42 是相同的,它只是函数中寄存器中的一个值,而不管它是如何传递给函数的?
-
如果这个关于编译器实现的问题,真的没有定义,作为 constexpr 值,编译器可以
movl将 42 写入代码中。
标签: c++ c++11 one-definition-rule forwarding-reference pass-by-const-reference