Ошибка C2228: слева от '.size' должен быть класс/struct/union

Я получаю эту ошибку компилятора при вызове vector 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;
}

Ответы

Ответ 1

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

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

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

Как правило, в С++, если что-то похоже на функцию, оно будет анализироваться как одно; это требует стандарт С++. Это действительно для обратной совместимости с 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);

Ответ 2

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

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

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