ошибка C2228: слева от .size должен быть класс / структура / объединение - PullRequest
18 голосов
/ 14 ноября 2010

Я получаю эту ошибку компилятора при вызове вектора size().Зачем?

#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cassert>


using namespace std;

class Vertex {

    float firstValue;
    float secondValue;
    float thirdValue;

    Vertex (float first, float second, float third){
          firstValue=first;
          secondValue=second;
          thirdValue=third;
    }

};


int main()
{
    cout<<"This program loads a 3D .off object. \nEnter the name of the file that describes it "<<endl;
    string inputFileName;
    getline(cin, inputFileName);

    ifstream inputFileStream;

    inputFileStream.open(inputFileName.data());
    assert (inputFileStream.is_open());

    string actualLine;

    for(;;){

        inputFileStream>>actualLine;

        istringstream actualLineStream(actualLine);



        std::vector<float> results( std::istream_iterator<int>(actualLineStream)
                        , std::istream_iterator<int>() );

       int resultsIndex=0;
       int resultsSize=results.size(); //WHY??

       while (resultsIndex<resultsSize){

         cout<<results[resultsIndex]<<endl;
       }


        if (inputFileStream.eof()) break;

    }


    ofstream outputChannel;

    while (true){} // to keep on console view 
    return 0;
}

Ответы [ 2 ]

51 голосов
/ 14 ноября 2010

Верьте или нет, эта строка не объявляет экземпляр std::vector с именем results, вызывая конструктор, принимающий итератор начала и конца:

std::vector<float> results(std::istream_iterator<int>(actualLineStream),
    std::istream_iterator<int>());

На самом деле объявляет функцию с именем results, которая принимает параметр с именем actualLineStream и другой безымянный параметр, оба типа std::istream_iterator<int>.

Обычно в C ++, если что-то выглядит как функция, оно будет проанализировано как единое целое; стандарт C ++ требует этого. Это действительно для обратной совместимости с C - но это настолько нелогично, что у него даже есть собственное имя: "самый неприятный синтаксический анализ" . Некоторые компиляторы даже выдают предупреждение, если встречаются самые неприятные разборы.

Это связано с тем, что эти две строки не эквивалентны в C ++:

Foo bar;   // Declares an instance of Foo named bar
Foo bar(); // Declares a function named bar that takes no parameters and returns a Foo

Чтобы исправить это, вы можете добавить несколько скобок вокруг одного из аргументов:

//                         +--------- Note extra parentheses!! ---------+
//                         |                                            |
//                         V                                            V
std::vector<float> results((std::istream_iterator<int>(actualLineStream)),
    std::istream_iterator<int>());

Или просто объявить каждый итератор отдельно:

std::istream_iterator<int> resultsBegin(actualLineStream);
std::istream_iterator<int> resultsEnd;
std::vector<float> results(resultsBegin, resultsEnd);
6 голосов
/ 14 ноября 2010

Я думаю, что вы нажали этот bugaboo .Вам удалось объявить results как новую функцию, которая возвращает std::vector<float>.Если я изменю строку, которая объявляет results на:

std::vector<float> results = std::vector<float>( std::istream_iterator<int>(actualLineStream), std::istream_iterator<int>() );

, я могу скомпилировать это (хотя с GCC, YMMV) * ​​1009 *

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