вызов оператора << временно - PullRequest
1 голос
/ 14 июля 2020

Рассмотрим следующий код ( 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 не может принимать rvalue, поскольку аргумент не является ссылкой const.

Но разве A и B не должны быть одинаковыми? И operator<< в STL, и в моем собственном берут левую часть как ссылку, отличную от 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<< segfault .

1 Ответ

3 голосов
/ 14 июля 2020

Так почему же они могут работать с временным объектом?

Потому что, в отличие от вашего operator <<, некоторые из стандартной библиотеки не бесплатны, а член функции , которые могут легко работать с временными объектами без каких-либо проблем, в то время как функции, не являющиеся членами, имеют явную перегрузку , принимающую rvalue (или, точнее, вперед) -ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...