【问题标题】:VS C++ overload as function for references to temporary objectsVS C++ 重载作为临时对象引用的函数
【发布时间】:2021-03-01 20:50:15
【问题描述】:

我正在使用带有 /std:c++latest 的 Visual Studio 2019 16.8.1 C++。我编写的代码使用对临时对象的引用来创建格式化输出。我知道这是有问题的,但到目前为止效果很好。

以下代码编译成功(带有cl /c /W4 /std:c++latest referenceBinding.cpp):

struct format {
    format& operator<<(int i);
};

void wusel() {
    format() << 1;
}

不幸的是,我希望将重载作为函数,而不是成员,因此我可以轻松添加新的重载。但是,这个代码

struct format {
    format& operator<<(int i);
};
format& operator<<(format& f, int i);
//format& operator<<(format&& f, int i);

void wusel() {
    format() << 1;
}

导致错误:

referenceBinding.cpp(16): error C2678: binary '<<': no operator found which takes a left-hand     operand of type 'format' (or there is no acceptable conversion)
referenceBinding.cpp(12): note: could be 'format &operator <<(format &,int)'
referenceBinding.cpp(16): note: while trying to match the argument list '(format, int)'

仅当我添加第二个(已注释掉的)右值引用重载时,它才能正常工作。我想知道,为什么?

顺便说一句:我知道/Zc:referenceBinding- 选项会将错误变成警告。

【问题讨论】:

  • 可能是一个错误。它至少从 msvc19.14 编译。

标签: c++ visual-studio templates


【解决方案1】:

在你的函数中

void wusel() {
    format() << 1;
}

format() 的返回值是一个右值。它不能绑定到左值引用。

如果 format 不需要修改,您可以使用 const format&amp; 来接受右值和左值,因为 const 引用可以绑定到两者。

format& operator<<(const format& f, int i);

另一种选择是使operator&lt;&lt; 成为模板并使用转发引用,然后它会在编译时检测您传递的是右值还是左值并使用适合调用的那个。

template <typename T>
format& operator<<(T&& f, int i);

使用模板解决方案,您很可能希望将模板限制为仅在T = format 的情况下作为重载被挑选出来。您可以使用 SFINAE 做到这一点。

template <typename T, std::enable_if_t<std::is_save_v<std::remove_reference_t<T>, format>>>
format& operator<<(T&& f, int i);

【讨论】:

    猜你喜欢
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-29
    • 1970-01-01
    • 1970-01-01
    • 2016-02-04
    相关资源
    最近更新 更多