2009-07-13 7 views
2

die folgende Klasse:Gibt es ein Funktionsobjekt zum Erstellen von Objekten in AWL? Betrachten

class Person { 
public: 
    // I don't want any "char *" to be converted to Person implicitly! 
    explicit Person(const char * name) : name_(name) {}; 

private: 
    std::string name_; 
}; 

Sehen Sie sich auch folgende Array von char * Daten:

char STUDENT_NAMES[][20] = { 
    "Bart", 
    "Liza", 
    "Maggie" 
}; 

Jetzt will ich std :: Liste der Person erstellen nach diesem Array. Alles, was ich erfinden könnte, ist std verwenden :: Transformationsalgorithmus mit handgeschriebenem Funktionsobjekt:

struct CreatePerson : public std::unary_function<const char*,Person> { 
    Person operator() (const char * name) const { 
     return Person(name); 
    }; 
}; 

// ... 

std::list<Person> students; 
std::transform(
    &STUDENT_NAMES[ 0 ], 
    &(STUDENT_NAMES[ sizeof(STUDENT_NAMES)/sizeof(STUDENT_NAMES[0]) ]), 
    front_inserter(students), 
    CreatePerson()); 
// ... 

Gibt es eine kürzer und/oder klare Weise es zu tun? Vielleicht einige Standard Funktionsobjekte oder Adapter?

Antwort

5

Sie können boost::lambda auf folgende Weise verwenden:

#include <boost/lambda/lambda.hpp> 
#include <boost/lambda/construct.hpp> 
#include <string> 
#include <iterator> 
#include <algorithm> 
#include <list> 

struct person { 
    explicit person(char const *name) 
    :name(name) { } 
private: 
    std::string name; 
}; 

int main() { 
    char names[][20] = { 
    "Michael", "litb" 
    }; 

    std::list<person> v; 
    std::transform(names, names + 2, std::front_inserter(v), 
    boost::lambda::constructor<person>()); 
} 

Ich glaube nicht, dass es mit der Standard C++ Library eine solche Art und Weise ist.

+0

Ich hoffe, dass dieses Array calcs jetzt sind endlich. Ignoriere meinen Blödsinn erwähnt, was ich in meiner Antwort vorübergehend hatte, was zu welchem ​​Typ führt. Srsly, Array hax am Morgen verletzt mein Gehirn :) Allerdings empfehle ich immer noch, 'STUDENT_NAMES' ein' char const * Namen [] = {"Bart", "Lisa", ...}; '- so zu machen es kann nicht mehr über die Grenze von 20 Zeichen hinauslaufen. Ich kenne Ihre Code-Basis jedoch nicht. Gab es einen guten Grund, dass du es so machst? –

+0

Ihre Lösung sieht gut aus, danke! Über die Array-Größe. Danke für Ihren Vorschlag, aber es ist nicht der Punkt des Problems. Mein Beispiel wird aus dem Zusammenhang genommen und zum leichteren Verständnis neu geschrieben. :) – Michael

+0

@litb: _const_ char Namen [] [20] führt zu keinen Verlagerungen für die Daten und damit ermöglicht die Daten in Nur-Lese-Speicher, wie EPROMs leben. OTHO, selbst _const_ char * Namen [] benötigt Umzüge (es ist ein Array von Zeigern, und diese Zeiger müssen verlagert werden): http://people.redhat.com/drepper/dsohowto.pdf –

0

nicht viel, ist aber nicht, dass es eine Standard-ELEMENTE-Makro für

sizeof(STUDENT_NAMES)/sizeof(STUDENT_NAMES[0]) 

Schnellsuche fand es nicht, aber ich fühle mich wie jede Implementierung ich verwendet habe, hat es.

Nur ein anderer Vorschlag, den ich habe, ist CreatePerson in eine Vorlage zu verwandeln - so, wenn Sie es noch einmal brauchen, müssen Sie nur CreateObj oder so etwas tun.

-1

Nun ich habe gerade geschrieben eine Methode/Funktion wie:

convert(const char*[] names, std::list<Person>&); 

Warum nicht, wenn nur eine einfache Umwandlung zu tun? Vielleicht vermisse ich den Punkt?

m2c

+0

Der Punkt ist in der Wiederverwendung Iterationscode in der Standard-Bibliothek definiert. Der 'algorithm'-Header enthält viele nützliche Funktionen für sehr häufige iterierende Tasks, die nicht auf Listen, Vektoren, Arrays beschränkt sind, sondern' Iteratoren 'verwenden. – xtofl

+0

@xtofl: Ja, ich stimme mit Ihnen überein. Mein Punkt ist, dass der hinzugefügte Wert in diesem Fall nicht offensichtlich ist, weil Sie in dem gegebenen Beispiel eine unäre Funktion außerhalb Ihres Klassenbereichs Person schreiben müssen, und nur um einen Standard-Transformationsalgorithmus anzuwenden. Ihre Lösung (mit Konstruktor) ist großartig und dort scheint die Verwendung von transform sauber zu sein. Aber schreiben ein unary nur um zu transformieren ... – neuro

2

Ihre Klasse Konstruktor ist eine Konvertierungsfunktion. Sie müssen nicht umwandeln: Sie können einfach einfügen. Werfen Sie einen Blick auf this code here.

std::list<Person> ps(NAMES, NAMES+sizeof(NAMES)/sizeof(NAMES[0])); 

Andernfalls eine kürzere Abhilfe wäre eine statische Factory-Funktion:

struct Person { 
    static Person create(const char* name); 
    .... 
}; 

std::transform(NAMES, NAMES+sizeof(NAMES)/sizeof(NAMES[0], front_inserter(ps), 
    &Person::create); 
+0

+1 dort scheint die Transformation viel mehr stylish als in der Frage Beispiel ... – neuro

+0

Nein, ist es nicht. Bitte beachten Sie, dass mein Konstruktor explizit ist. Zweites Beispiel mit statischen create() funktioniert wirklich gut, aber es ist nur schön aussehende Adoption von mir. Sie haben gerade die Funktionalität von funktor in die statische Methode verschoben. Trotzdem danke. Was ich sehen wollte, ist eine Methode, um mein Objekt direkt zu erstellen. Für jetzt scheint es mir, gibt es keine solche Fähigkeit in STL. – Michael

+0

Sie sind völlig richtig. Du hast nach einem schöneren Weg gefragt - nur ein bisschen: Du brauchst den zusätzlichen Funktor nicht. – xtofl

Verwandte Themen