临时调用 operator<<
call operator<< on temporary
考虑以下代码 (godbolt):
#include <fstream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
using namespace std::string_literals;
template<class CharT, class Traits>
void test(std::basic_ostream<CharT, Traits> &s) {
s << "Other test\n"s;
}
struct my_struct {
std::string s = "My Struct\n"s;
};
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &stream,
const my_struct &s) {
stream << s.s;
return stream;
}
int main() {
fs::path file("test.txt");
const my_struct s;
// A
operator<<(std::ofstream(file, std::ios_base::app), "Other test!\n"s); // Runs fine
std::ofstream(file, std::ios_base::app) << "Das ist ein Test!\n"s; // Runs fine
// B
operator<<(std::ofstream(file, std::ios_base::app), s); // Runs fine
std::ofstream(file, std::ios_base::app) << s; // Runs fine
// C
// test(std::ofstream(file, std::ios_base::app)); // Does not compile
}
A 和 B 部分的代码编译得很好,而 C 部分则不行。很明显 test
不能取右值,因为参数是非 const
引用。
但是 A
和 B
不应该相同吗? STL 的 operator<<
和我自己的都将左侧作为非 const
参考。那么为什么他们可以使用临时对象呢?
编译器:
clang version 10.0.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
编辑:问题的第一个版本有一个错误,造成了自己的 operator<<
段错误。
So why is it possible for them to work with a temporary object?
因为,与您的 operator <<
不同,标准库中的某些内容不是免费的,而是 member functions which can readily work on temporary objects without any problem, while the non-member functions have an explicit overload 采用右值(或更精确的前向)引用。
考虑以下代码 (godbolt):
#include <fstream>
#include <string>
#include <filesystem>
namespace fs = std::filesystem;
using namespace std::string_literals;
template<class CharT, class Traits>
void test(std::basic_ostream<CharT, Traits> &s) {
s << "Other test\n"s;
}
struct my_struct {
std::string s = "My Struct\n"s;
};
template<class CharT, class Traits>
std::basic_ostream<CharT, Traits> &operator<<(std::basic_ostream<CharT, Traits> &stream,
const my_struct &s) {
stream << s.s;
return stream;
}
int main() {
fs::path file("test.txt");
const my_struct s;
// A
operator<<(std::ofstream(file, std::ios_base::app), "Other test!\n"s); // Runs fine
std::ofstream(file, std::ios_base::app) << "Das ist ein Test!\n"s; // Runs fine
// B
operator<<(std::ofstream(file, std::ios_base::app), s); // Runs fine
std::ofstream(file, std::ios_base::app) << s; // Runs fine
// C
// test(std::ofstream(file, std::ios_base::app)); // Does not compile
}
A 和 B 部分的代码编译得很好,而 C 部分则不行。很明显 test
不能取右值,因为参数是非 const
引用。
但是 A
和 B
不应该相同吗? STL 的 operator<<
和我自己的都将左侧作为非 const
参考。那么为什么他们可以使用临时对象呢?
编译器:
clang version 10.0.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0
Found candidate GCC installation: /usr/lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Selected GCC installation: /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/10.1.0
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
编辑:问题的第一个版本有一个错误,造成了自己的 operator<<
段错误。
So why is it possible for them to work with a temporary object?
因为,与您的 operator <<
不同,标准库中的某些内容不是免费的,而是 member functions which can readily work on temporary objects without any problem, while the non-member functions have an explicit overload 采用右值(或更精确的前向)引用。