当空变量没有定义时,按值传递它们是否安全



如果我按值传递一个空变量,即使它没有定义,它是否安全且兼容?

我在编写代码时遇到了这个问题,重载了|,以便打印矢量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;
}

将其移动到页眉

如果我将其移动到标头中,我可以使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,并且没有给出任何定义?

是否需要编译器才能使我的v|print示例正常工作?需要澄清的是,印刷品在哪里是extern,并且没有给出任何定义?

否。您正在使用print进行odr(您正在调用一个不产生常量表达式的左值到右值转换),这意味着您需要一个print的定义。然而,这是一类不正确的错误,不需要诊断。由于有问题的代码不会将print的地址带到任何地方,因此编译器很可能会发出不需要这样定义的代码,因此链接器也会对此感到高兴。通常情况下,它将只是工作™。

更好的解决方案是简单地将声明更改为printconstexpr:

constexpr print_tag_t print{};

现在,v | print不会使用print(因为左值到右值的转换现在将是一个常量表达式),所以甚至不需要定义,所以程序格式良好。

相关内容

  • 没有找到相关文章

最新更新