2010-11-14 5 views
16

Je reçois cette erreur de compilation lors de l'appel size() du vecteur. Pourquoi?erreur C2228: gauche de '.size' doit avoir class/struct/union

#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; 
} 

Répondre

48

Croyez-le ou non, cette ligne ne Déclarez une instance de std::vector nommé results, appelant le constructeur de prendre un début et de fin iterator:

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

Cette réalité déclare une fonction appelé results qui prend un paramètre nommé actualLineStream et un autre paramètre sans nom, tous deux de type std::istream_iterator<int>.

Généralement en C++, si quelque chose ressemble à une fonction, il sera analysé comme un; la norme C++ l'exige. C'est vraiment pour la rétrocompatibilité avec C - mais c'est si contre-intuitif qu'il a même son propre nom: le "most vexing parse". Certains compilateurs vont même émettre un avertissement s'il rencontre l'analyse la plus vexante.

Il est lié au fait que ces deux lignes ne sont pas équivalents en 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 

Pour résoudre ce problème, vous pouvez ajouter plusieurs parenthèses autour d'un des arguments:

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

Ou simplement déclarer chaque iterator séparément:

std::istream_iterator<int> resultsBegin(actualLineStream); 
std::istream_iterator<int> resultsEnd; 
std::vector<float> results(resultsBegin, resultsEnd); 
+4

Wow .. Je n'aurais jamais pensé à cela. – andandandand

+0

Je suis tellement content d'avoir trouvé cet article. Ce comportement est terrible. –

+0

Ouais, Dieu merci, j'ai trouvé ça. J'étais prêt à jeter mon ordinateur portable par la fenêtre. – MikeTheLiar

6

Je pense que vous frappez this bugaboo . Vous avez réussi à déclarer results comme une nouvelle fonction qui renvoie un std::vector<float>. Si je change la ligne qui déclare results à:

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

Je peux compiler ce (avec GCC, cependant, YMMV)

Questions connexes