Почему istream не поддерживает извлечение значений - PullRequest
0 голосов
/ 03 ноября 2018

У меня есть класс, который обтекает std::string для обеспечения форматирования:

struct Wrap {
  std::string& s; // need const ref for output, non const for input 
  friend std::ostream& operator<< (std::ostream& os, const Wrap& w) {
    os << "[" << w.s << "]";
    return os;
  }
  friend std::istream& operator>> (std::istream& is, Wrap&& w) {
    Is >> ......;
    return is;
  }
};

И с выводом все в порядке:

my_ostream << Wrap{some_string};

Потому что привязка временного переноса к const ref в порядке.

Но менее хорошо с вводом:

my_istream >> Wrap{some_string}; // doesn't compile - cannot bind lvalue to rvalue

Я, вероятно, собираю его, но так как я не видел >> &&, то что-то не так.

Является ли >>&& запрещенным или каким-либо злом?

Ответы [ 2 ]

0 голосов
/ 03 ноября 2018

(протестировано на gcc версии 7.3.0 (Ubuntu 7.3.0-16ubuntu3))

Ваш код работает как есть (запустите здесь: http://cpp.sh/9tk5k):

#include <string>
#include <iostream>


struct Wrap {
  std::string& s; // need const ref for output, non const for input 
  friend std::ostream& operator<< (std::ostream& os, const Wrap& w) {
    os << "[" << w.s << "]";
    return os;
  }
  friend std::istream& operator>> (std::istream& is, Wrap&& w) {
    is >> w.s;
    return is;
  }
};


int main() {
    std::string a = "abcd";
    std::cin >> Wrap{a};
    std::cout << Wrap{a};
}

Вы должны быть в состоянии передать Wrap как r-значение. Если вы создаете это in-line, это именно то, что происходит.

Привязка r-значения к константному ref также должна (и работает).

0 голосов
/ 03 ноября 2018

Ссылка на rvalue может быть привязана только к rvalue. В большинстве случаев это именно то, что вам нужно - это гарантирует (например), что когда вы пишете оператор ctor / assignment move, вы случайно не вызовете его для lvalue и не уничтожите то, что все еще будет использоваться.

Я не уверен, почему вы хотите использовать ссылку на rvalue в этом случае, но есть причина, по которой вам это действительно нужно, вы можете по крайней мере использовать тот же синтаксис, когда это параметр шаблона:

struct Wrap
{
    std::string s; // need const ref for output, non const for input
    friend std::ostream &operator<<(std::ostream &os, const Wrap &w)
    {
        os << "[" << w.s << "]";
        return os;
    }

    template <class T>
    friend std::istream &operator>>(std::istream &is, T &&w)
    {
        is >> w.s;
        return is;
    }
};

int main() {
    int x;

    Wrap w;

    std::cin >> w;
}

Не уверен, что это действительно полезно.

...