2

文字列をファクトリ関数にマップするグローバルマップを作成しようとしています。これにより、ビルダー関数でiniファイルからキーを読み取り、そのiniファイルとその関連セクションを正しいファクトリ関数に渡すことができます。グローバルマップを含むヘッダーのコードは次のとおりです。

typedef Primitive* (*factory_func_t)(const ::INI&, const std::string&);

const std::map<std::string, factory_func_t> factory_funcs = {
    { SphereFactory::ID,     &SphereFactory::create_sphere },
    { QuadFactory::QUAD_ID,  &QuadFactory::create_quad },
    { QuadFactory::PQUAD_ID, &QuadFactory::create_pquad }
};

そして、これらのファクトリクラスの1つの例を次に示します。

class SphereFactory
{
  public:
    static const std::string ID;

    static Sphere* create_sphere(const ::INI&, const std::string& section);

    SphereFactory() = delete;

  private:
    static const std::string CENTER_KEY;
    static const std::string RADIUS_KEY;
};

const std::string SphereFactory::ID = "Sphere";

const std::string SphereFactory::CENTER_KEY = "Center";
const std::string SphereFactory::RADIUS_KEY = "Radius";

これはすべて、コンパイル時にエラーを発生させます。

error: could not convert `{{cg::prim::factory::SphereFactory::ID,
 cg::prim::factory::SphereFactory::create_sphere}, 
 {cg::prim::factory::QuadFactory::QUAD_ID, 
 cg::prim::factory::QuadFactory::create_quad}, 
 {cg::prim::factory::QuadFactory::PQUAD_ID, 
 cg::prim::factory::QuadFactory::create_pquad}}'
 from `<brace-enclosed initializer list>'
 to `const std::map<std::basic_string<char>, cg::Primitive* (*)(const INI&, 
 const std::basic_string<char>&)>'

上記のコードはすべてcg::prim::factory、違いが生じる場合に備えて、名前空間に含まれています。Quadとから継承SpherePrimitiveます。私はg++ -O3 -Wall -Wextra -pedantic -std=c++11コンパイルに使用しています。

なぜこれがコンパイルされないのですか?

4

1 に答える 1

3

共変の戻り型を使用しようとしています。これtypedefはforですPrimitive *が、ファクトリは戻りSphere *ますなど。基本型を返す代替のラッパーファクトリ関数を含めることができます。

現状では、C ++は、ベースポインタと派生ポインタを返す関数の間に関係を認識していません。virtualこの方法で「変換」できるのは関数のみであり、ファクトリを仮想化することはできません。(または、少なくとも、C ++では、仮想関数を持つファクトリオブジェクトは推奨されません。これはJavaでは一般的ですが、ここではラッパー関数の方が適しています。)

初期化子リストはまだ初期段階にあるため、デバッグする(そして、まだ存在する可能性のある潜在的なコンパイラーのバグを回避する)1つの方法は、可能な限り手動でキャストすることです。

const std::map<std::string, factory_func_t> factory_funcs = {
    { SphereFactory::ID,     (factory_func_t) &SphereFactory::create_sphere },
    { QuadFactory::QUAD_ID,  (factory_func_t) &QuadFactory::create_quad },
    { QuadFactory::PQUAD_ID, (factory_func_t) &QuadFactory::create_pquad }
};
于 2012-06-06T12:16:38.100 に答える