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

这是其中一个工厂类的示例:

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

您正在尝试使用协变返回类型:typedefis forPrimitive *但工厂 returnSphere *等。您可能包括返回基本类型的替代包装工厂函数。

事实上,C++ 认为返回基指针和派生指针的函数之间没有任何关系。只virtual允许以这种方式“转换”函数,工厂不能是虚拟的。(或者至少,在 C++ 中不鼓励使用具有虚函数的工厂对象。这在 Java 中很常见,但这里使用包装函数会更好。)

由于初始化列表仍处于起步阶段,一种调试方法(并解决可能仍然存在的潜在编译器错误)是尽可能手动转换:

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 回答