2

現在、入力を受け取り、次のアクションのいずれかを選択するswitchステートメントがあります。

オプション1

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).model);
}

オプション2

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).manufacturer);
}

オプション3

for(; i < queue_size; ++i)
{
   prepared->setString(i+1, queue.at(i).name);
}

PHPでは、次のようなことを行うのと同じことができます。

$queue[i][$member];

$ memberは、「name」、「manufacturer」などに設定できます。

C ++で同様またはより堅牢なことを行う方法はありますか?

ヘルプ/提案を事前に感謝します!

4

6 に答える 6

4

C++11がない場合は、C++11 std::functionまたはboost::functionを使用します。

std::map<YourSwitchType, std::function<void(void)> functionMap;

次に、次のような関数を定義します

void manufacturString() {
  for(; i < queue_size; ++i) {
    prepared->setString(i+1, queue.at(i).manufacturer);
  }
}

ケースごとに、これらをマップに入力します。

functionMap[someSwitchValue] = std::bind(&ThisType::manufactureString, this);

次に、それらを呼び出すことができます:

functionMap[someSwitchValue]();

このアプローチの利点の 1 つは、メンバー関数に限定されないことです。非メンバー関数、ファンクター、静的メンバー、および非メンバー関数を同じマップに配置できます。唯一の制限は、バインド後に void を返し、引数を取らないことです (これはこの例に固有です)。

于 2012-05-18T08:03:27.160 に答える
3

mapこれは、プロパティ名からメンバーへのポインタへのaを使用して行うことができます。しかし、それは少し手間がかかり(自分でそのマッピングを作成する必要があります)、構文は少し厄介になります。(そして、この方法で対処したいすべてのメンバーは、同じタイプでなければなりません。)

デモ:

#include <iostream>
#include <map>

struct Foo {
    std::string name;
    std::string address;
};

typedef std::string Foo::* FooMemPtr;
typedef std::map<std::string, FooMemPtr> propmap;

int main()
{
    propmap props;
    props["name"] = &Foo::name;
    props["address"] = &Foo::address;

    /* ... */

    Foo myfoo;
    myfoo.*(props["name"]) = "myname";
    myfoo.*(props["address"]) = "myaddress";
    std::cout << myfoo.*(props["address"]) << std::endl;
    std::cout << myfoo.*(props["name"]) << std::endl;
}
于 2012-05-18T08:07:16.523 に答える
1

文字列の代わりに列挙型を使用できる場合は、列挙型の値からインデックス化された名前、製造元などにアクセスできます。それは、あなたがどれだけダイナミックである必要があるかによって異なります。

于 2012-05-18T08:05:57.227 に答える
0

これを実行するには、 STL マップを使用します。これは、PHP で行う場合と同じように機能します。

于 2012-05-18T07:59:32.447 に答える
0

1 つのオプションは、extractor ファンクターを関数に渡すことです。

#include <string>
#include <vector>
#include <boost/bind.hpp>

struct Some {
    std::string model, manufacturer, name;
};

struct Prepared {
    void setString(size_t, std::string const&);
};

template<class Extractor>
void foo(Extractor extract) {
    Prepared* prepared = 0;
    std::vector<Some> queue;
    size_t i, queue_size = queue.size();
    for(; i < queue_size; ++i) {
        prepared->setString(i+1, extract(queue.at(i)));
    }
}

int main() {
    // C++03
    foo(boost::bind(&Some::model, _1));
    foo(boost::bind(&Some::manufacturer, _1));
    foo(boost::bind(&Some::name, _1));

    // C++11
    foo([](Some const& some){ return some.model; });
    foo([](Some const& some){ return some.manufacturer; });
    foo([](Some const& some){ return some.name; });
}
于 2012-05-18T08:14:58.197 に答える
0

この種のことは、メンバー変数ポイントを使用して行うことができます (メンバー関数ポインターもあります)。ブースト バインド関数はより一般的ですが、これは最終的にその下で行っていることです (少なくともこのシナリオでは)。

#include <iostream>
#include <string>

struct item
{
    std::string a, b;
};

//the really ugly syntax for a pointer-to-member-variable
typedef std::string item::*mem_str;

//show each member variable from the list
void show_test( item * objs, size_t len, mem_str var )
{
    for( size_t i=0; i < len; ++i )
        std::cout << objs[i].*var << std::endl;
}

int main()
{
    //create some test data
    item test[2];
    test[0].a = "A-Zero";
    test[0].b = "B-Zero";

    test[1].a = "A-One";
    test[1].b = "B-One";

    //show variables
    show_test( test, 2, &item::a );
    show_test( test, 2, &item::b );

    return 0;
}
于 2012-05-18T11:51:48.327 に答える