在没有定义的情况下按值传递空变量是否安全?
Safe to pass empty variables by value, when they have no definition?
如果我按值传递一个空变量,即使它没有定义,它是否安全且合规?
我在处理代码时遇到了这个问题,重载 |
,使它打印向量 v
:
的内容
v | print; // prints the vector v
我在这里提供的代码适用于 g++
和 clang
,即使 print
是一个没有链接的 extern
变量,但我想知道我是否将标准推得太远了。这是针对 c++11/c++14 的,我猜这是在 c++17 中用 inline
变量解决的?
首先,我的初始代码。目标是允许像 v|print
这样的东西打印一个矢量。我也有更大的目标,与范围有关,但我将在这里关注这个小例子
struct print_tag_t {};
print_tag_t print;
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
int main() {
std::vector<int> v{2,3,5,7};
v | print;
}
将其移动到 header
如果我将其移动到 header,我可以将 operator|
重载为 inline
。但是 print
呢?我发现我可以使它 extern
来避免关于重复符号的链接器错误
// print.hh
struct print_tag_t {};
extern // extern, as I can't use inline on a variable
print_tag_t print;
inline
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
这对我有用。不知何故,即使 print
没有定义,我也可以做 v|print
。我想这是因为它是空的,因此没有检查的价值,因此它永远不需要地址。
编译器是否需要允许我的 v|print
示例工作?澄清一下,print
是 extern
并且没有给出任何定义?
Are compilers required to allow my v|print
example to work? Where, to clarify, print is extern
and hasn't been given any definition?
没有。您正在使用 print
(您正在调用不产生常量表达式的左值到右值的转换),这意味着您需要 print
的定义。但是,这是格式错误的错误类别之一,不需要诊断。并且由于所讨论的代码没有在任何地方使用 print
的地址,编译器很可能会发出不需要这样定义的代码,因此链接器也会对此感到高兴。通常,它会 Just Work™。
更好的解决方案是简单地将声明更改为 print
constexpr
:
constexpr print_tag_t print{};
现在,v | print
不会使用 print
(因为左值到右值的转换现在是常量表达式),所以甚至不需要定义,所以程序是良构的。
如果我按值传递一个空变量,即使它没有定义,它是否安全且合规?
我在处理代码时遇到了这个问题,重载 |
,使它打印向量 v
:
v | print; // prints the vector v
我在这里提供的代码适用于 g++
和 clang
,即使 print
是一个没有链接的 extern
变量,但我想知道我是否将标准推得太远了。这是针对 c++11/c++14 的,我猜这是在 c++17 中用 inline
变量解决的?
首先,我的初始代码。目标是允许像 v|print
这样的东西打印一个矢量。我也有更大的目标,与范围有关,但我将在这里关注这个小例子
struct print_tag_t {};
print_tag_t print;
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
int main() {
std::vector<int> v{2,3,5,7};
v | print;
}
将其移动到 header
如果我将其移动到 header,我可以将 operator|
重载为 inline
。但是 print
呢?我发现我可以使它 extern
来避免关于重复符号的链接器错误
// print.hh
struct print_tag_t {};
extern // extern, as I can't use inline on a variable
print_tag_t print;
inline
void operator| (std::vector<int> & x, decltype(print) ) {
for(auto elem : x) {
std::cout << elem << '\n';
}
}
这对我有用。不知何故,即使 print
没有定义,我也可以做 v|print
。我想这是因为它是空的,因此没有检查的价值,因此它永远不需要地址。
编译器是否需要允许我的 v|print
示例工作?澄清一下,print
是 extern
并且没有给出任何定义?
Are compilers required to allow my
v|print
example to work? Where, to clarify, print isextern
and hasn't been given any definition?
没有。您正在使用 print
(您正在调用不产生常量表达式的左值到右值的转换),这意味着您需要 print
的定义。但是,这是格式错误的错误类别之一,不需要诊断。并且由于所讨论的代码没有在任何地方使用 print
的地址,编译器很可能会发出不需要这样定义的代码,因此链接器也会对此感到高兴。通常,它会 Just Work™。
更好的解决方案是简单地将声明更改为 print
constexpr
:
constexpr print_tag_t print{};
现在,v | print
不会使用 print
(因为左值到右值的转换现在是常量表达式),所以甚至不需要定义,所以程序是良构的。