2010-11-28 3 views
3

Ich verwende g ++ in CodeBlocks IDE in Ubuntu. Ich bin neu in STL und ein Teil von C++.Einige Probleme beim Lernen von STL

Q1: // beantwortete

std::istream_iterator<std::string> begin (dictionaryFile); 
std::istream_iterator<std::string> end; 
std::vector< std::string> dictionary; 
std::copy (begin, end, std::back_inserter (dictionary)); 

richtig ist, aber wenn ich geändert

std::istream_iterator<std::string> end; 

in

std::istream_iterator<std::string> end(); 

der Compiler sagt keinen passenden Funktionsaufruf in der vierten Zeile.

Q2: // sorry ich nicht geschafft haben klar das Problem das erste Mal

struct PS : std::pair< std::string, std::string > { 
PS(); 
static struct FirstLess: std::binary_function< PS, PS, bool> { 
    bool operator() (const PS & p, const PS & q) const { 
     return p.first < q.first; 
    } 
} firstLess1; }; 


struct FirstLess: std::binary_function< PS, PS, bool> { 
bool operator() (const PS & p, const PS & q) const { 
    return p.first < q.first; 
}} firstLess2; 

Beachten Sie, dass der einzige Unterschied zwischen firstLess1 und firstLess2 ist, dass firstLess1 in PS deklariert wird.

, wenn ich die Funktion aufrufen:

k = std::find_if (j + 1, finis, std::not1 (std::bind1st (PS::firstLess1, *j))); 

der Compiler gab mir einen Fehler 'undefined reference to PS :: firstLess1'. und dann wechselte ich zu

k = std::find_if (j + 1, finis, std::not1 (std::bind1st (firstLess2, *j))); 

dann übergeben sie die Kompilierung.

Mehr seltsam, in einem anderen Teil des Programms verwenden ich sowohl

j = std::adjacent_find (j , finis, PS::firstLess1); 
j = std::adjacent_find (j , finis, firstLess2); 

und die Compiler hat gab mir keinen Fehler.

+0

OK. Ich habe herausgefunden, wie ich die zweite Frage lösen kann (aber ich weiß immer noch nicht warum) benutze einfach k = std :: find_if (j + 1, finis, std :: nicht1 (std :: bind1st (PS :: FirstLess(), * j))); ist OK oder Sie können const PS :: FirstEqual PS :: ersteEqual1 = PS :: FirstEqual(); nach der Erklärung. – user522829

Antwort

4

std::istream_iterator<std::string> end(); C++ interpretiert dies als Erklärung der Funktion, deren Name ist end Rückgabewert Typ ist std::istream_iterator<std::string> und Argumentliste ist leer. Deshalb bekommst du solche Fehler. In C++, um irgendein Objekt durch Aufruf des Standardkonstruktors seiner Klasse zu machen, müssen Sie dies tun type_name variable_name;. type_name variable_name(); wird als Funktionsdeklaration interpretiert.

+1

Dies nennen wir [das ärgerlichste Parse] (http://en.wikipedia.org/wiki/Most_vexing_parse). –

1

A1:

Ein Objekt, dessen Initialisierer ist ein leerer Satz von Klammern, das heißt,(), wird Wert initialisiert werden.

[Hinweis: Da() wird nicht durch die Syntax für Initialisierer gestattet,

X a();

ist nicht die Erklärung der ein Objekt der Klasse X, aber die Erklärung der Funktion kein Argument nimmt, und ein X.

Die Form zurückkehrt() in bestimmten anderen Zusammenhängen Initialisierung erlaubt ist (5.3.4, 5.2 .3, 12.6.2). - Endnote]

A2:

Ich bin nicht wirklich sicher, was Sie wollen, std :: find_if und std :: adjacent_find etwas tun comepletely anders.Aber wie auch immer, hier ist ein von dir inspirierter Arbeitscode.

#include <iostream> 
#include <algorithm> 
#include <string> 
#include <vector> 

typedef std::pair<std::string, std::string> TwoStrings; 

struct FirstLess : std::binary_function<TwoStrings, TwoStrings, bool> 
{ 
    bool operator() (const TwoStrings& p, const TwoStrings& q) const { 
     return p.first < q.first; 
    } 
}; 

int main() 
{ 
    std::vector<TwoStrings> v; 
    std::vector<TwoStrings>::iterator it; 
    v.push_back(TwoStrings("4. Here's ", "Johnny")); 
    v.push_back(TwoStrings("1. Here's ", "Johnny")); 
    v.push_back(TwoStrings("2. Here's ", "Johnny")); 
    v.push_back(TwoStrings("2. Here's ", "Johnny")); 
    v.push_back(TwoStrings("3. Here's ", "Johnny")); 

    it = std::adjacent_find(v.begin(), v.end(), FirstLess()); 
    std::cout << it->first << it->second << std::endl; 

    it = std::find_if(v.begin() , v.end(), std::not1(std::bind1st(FirstLess(), *(v.begin())))); 
    std::cout << it->first << it->second << std::endl; 
} 

A die Ausgabe ist:

1. Here's Johnny 
4. Here's Johnny 
2

A1: bereits
A2 ausreichend beantwortet: fügen eine const auf die Erklärung von firstLess, OR die firstLess definieren Objekt in einer CPP-Datei (siehe this)

+0

+1 für * Definieren Sie das firstLess-Objekt *, und zwar im umschließenden Bereich (siehe die oberste Zeile der verknüpften Seite). In diesem Fall macht das Hinzufügen von 'const' keinen Unterschied, da dies nur für statische Member vom Integraltyp, nicht für Strukturen, funktioniert. (Was überraschend ist, ist, dass der Compiler den 'ancient_find()' Aufruf erlaubt.) –

+0

@j_random_hacker: gefixt. Aber sollte es wirklich nur für integrale Typen wrek? es hat bei mir mit POD Strukturen auch in der Vergangenheit funktioniert ... – smerlin

+0

Ich weiß es nicht :) Ich kann nur sagen, dass es nicht erwartet werden sollte, dass es funktioniert. Aber einem Compiler steht es frei, alles zuzulassen, was dem Standard nicht widerspricht, und ich glaube nicht, dass dies der Fall ist. –

Verwandte Themen