Почему это не компилируется? - PullRequest
4 голосов
/ 06 декабря 2009

Когда я пытаюсь объявить iss с помощью первой формы, g ++ выдает мне «error: нет совпадения для 'operator >>' в 'iss >> s'". Но разве две разные декларации не делают одно и то же?

#include <iostream>
#include <sstream>
#include <string>


int main() {
    const char *buf = "hello world";
    std::string ss(buf);
    //std::istringstream iss(std::string(buf)); // this doesn't work
    std::istringstream iss(ss); // but this does
    std::string s;
    iss >> s;
}

Ответы [ 5 ]

11 голосов
/ 06 декабря 2009

Это известно как «самый неприятный синтаксический анализ» в C ++: то, что для вас выглядит как объявление экземпляра, на самом деле выглядит как объявление функции для компилятора.

std::string name(); //function declaration
std::string name;  //object declaration with default constructor

std::stringstream ss(std::string(buf));  //function declaration
std::stringstream ss(std::string buf);  //another function declaration
std::stringstream ss(std::string);  //also a function declaration
std::stringstream ss(std::string());  //ditto, argument names are optional

std::stringstream ss((std::string(buf))); //object declaration

Обратите внимание на дополнительные скобки в последнем примере. Эти скобки не будут допустимы в объявлении функции.

Первый пример с конструктором по умолчанию хорошо известен. Во втором случае неясность добавляет, что скобки вокруг имен параметров в C ++ являются допустимыми, но необязательными. Например, вы можете определить функцию следующим образом:

void foo(int (bar))
{}

По сути, вы сталкиваетесь с этим каждый раз, когда все аргументы конструктора являются временными значениями от вызовов конструктора, которые принимают 0 или 1 аргумент, и быстрое решение состоит в том, чтобы заключить в один из аргументов дополнительные скобки.

8 голосов
/ 06 декабря 2009

Это потому, что istringstream принимает константную ссылку на строку. Так что вы не можете просто написать это:

std::istringstream iss(std::string(buf));

На самом деле вы можете, но это означает, что вы объявляете функцию iss, которая принимает std::string и возвращает std::istringstream. Эквивалентно, вы могли бы написать:

std::istringstream iss(std::string buf);

Это довольно больные вещи C ++.

0 голосов
/ 06 декабря 2009

Первый аргумент для создания istream из строки должен быть: const string & str , что не создает:

    std::string(buf)

В то время как следующий код иллюстрирует эту точку, она теряет память, , поэтому на самом деле не используйте ее.

    std::istringstream iss(*new std::string(buf));
0 голосов
/ 06 декабря 2009

Я предполагаю, что есть некоторая путаница с типом, возвращаемым std :: string (char *), потому что это:

  std::istringstream iss((std::string)std::string(buf));

работает.

0 голосов
/ 06 декабря 2009

Вам не нужно использовать namespace std;?

...