2009-07-13 10 views
2

は、次のクラスを考えてみましょう:STLにオブジェクトを作成する関数オブジェクトはありますか?

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

ものchar *データの配列を以下の点を考慮:

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

今、私はこの配列に基づいて人のSTD ::リストを作成したいです。 私が考案可能性すべてはSTDを使用することです::手書き 関数オブジェクトに変換アルゴリズムを:

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()); 
// ... 

は、任意の短くおよび/または明確な方法はそれを行うにはありますか?たぶん標準の 関数オブジェクトまたはアダプタですか?

答えて

5

あなたは次のようにboost::lambdaを使用することがあります。

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

を、私は、標準C++ライブラリと、そのような方法があるとは思いません。

+0

私は、この配列のCALCSは最終的に、今ある願っています。どのようなタイプのものが得られるかについて私の答えで私が一時的に何を持っていたのか、私の愚痴を無視してください。 Srsly、朝の配列haxは私の脳を傷つける:)しかし、私は 'STUDENT_NAMES'を' char const * names [] = {"Bart"、 "Lisa"、...}; 'にすることをお勧めしますもはや20文字制限をオーバーフローさせることはできません。私はあなたのコードベースを知っているわけではありません。あなたがそうする強い理由はありましたか? –

+0

あなたのソリューションはよく見えます、ありがとう! アレイのサイズについて。あなたの提案に感謝しますが、それは問題のポイントではありません。私の例は文脈から取り除かれ、理解を容易にするために書き直されています。 :) – Michael

+0

@litb:_const_ char names [] [20]はデータの再配置を起こさないため、データはEPROMなどの読み取り専用メモリに格納されます。他にも_const_char * names []でも再配置が必要です(ポインタの配列であり、それらのポインタを再配置する必要があります): http://people.redhat.com/drepper/dsohowto.pdf –

0

あまり助けますが、クイック検索

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

のための標準的な要素マクロはありませんが、それを見つけられませんでしたが、私はそれを持って使用しているすべての実装のように感じます。

私が持っている他の提案は、CreatePersonをテンプレートに変えることです。あなたがもう一度それを必要としたら、CreateObjかそのようなことをするだけです。

-1

まあ、私はちょうどのような方法/機能書かれています:

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

はなぜ単純な変換をしない場合は?多分私はポイントを欠場?

M2C

+0

ポイントは標準ライブラリで定義されている反復コードを再利用しています。 'アルゴリズム'ヘッダーには、非常に一般的な反復タスク(リスト、ベクトル、配列に限らず、イテレーターを使用する)に役立つ関数が多数含まれています。 – xtofl

+0

@xtofl:はい、私はあなたと交渉します。私の指摘は、この例では、Personクラススコープの外に単項関数を書く必要があり、標準変換アルゴリズムを適用するだけなので、この場合の追加値は明白ではないという点です。あなたのソリューション(コンストラクタを使用)は素晴らしいですし、変換の使用はきれいに見えます。しかし単なる変換を使用するために単項を書く... – neuro

2

あなたのクラスのコンストラクタは変換関数です。変換する必要はありません。挿入するだけです。 this code hereをご覧ください。

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

そうでない場合は、短いこの問題を回避するには、静的なファクトリ関数を使用して次のようになります。

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

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

+1変換は質問の例よりももっとスタイリッシュに見える... – neuro

+0

いいえ、それはありません。私のコンストラクタは明示的であることに注意してください。 静的なcreate()を使用した2番目の例は実際にはうまく動作しますが、それは魅力的なものです。ファンクタから静的メソッドに機能を移したばかりです。とにかくありがとうございました。 私が見たいのは、自分のオブジェクトを直接作成する方法です。今のところ、STLにはそのような能力はないようです。 – Michael

+0

あなたはまったく正しいです。あなたはより良い方法を求めました - ちょっとだけ:あなたは余分なファンクタを必要としません。 – xtofl

関連する問題