C++模板通过 Enum 指定类型

发布于 2024-10-17 23:57:17 字数 382 浏览 1 评论 0原文

我面临一个问题: 我想创建一个函数,它根据函数将接收的枚举来调用特定的模板类型构造函数。我的意思是:

  typedef   ____ (Class<whatever>::*tabType)(int flag);

  template<typename T>
  static Class*  Class<t>::createClassInstance(enum precision)
  {
    static const ___ createTab[] = {
    Class<int>,
    Class<double>
    }
   return (new createTab[precision](1));
  }

I'm facing a problem :
I want to create a function which calls a specific template type constructor depending on a enum that the function will receive. By that i mean :

  typedef   ____ (Class<whatever>::*tabType)(int flag);

  template<typename T>
  static Class*  Class<t>::createClassInstance(enum precision)
  {
    static const ___ createTab[] = {
    Class<int>,
    Class<double>
    }
   return (new createTab[precision](1));
  }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

属性 2024-10-24 23:57:18

如果枚举值作为函数参数是动态的,则必须使用调度表或 switch/if-else。请注意,您的伪代码没有清楚地解释要求。比如说,您到底想要定义什么 createInstance 函数以及如何调用它?

If the enum value is dynamic as a function argument, you'll have to use either a dispatch table or switch/if-else. Notice that your pseudo code does not clearly explain the requirement. Say, what exactly the createInstance function you wish to define and how is it going to be called?

情绪操控生活 2024-10-24 23:57:18

我想说,只需构建一个将枚举映射到工厂函数(boost::function<>)的std::map即可。然后,您只需为所需的每种类型添加一个条目及其相应的enum。实际构建工厂功能。您可以为每个类使用一些静态 Create() 函数并存储函数指针。或者,您可以使用 Boost.Lambda 构造函数/析构函数 函子。或者,您可以使用 Boost.Bind 来构造函子包装需要一定数量参数的工厂函数。这是一个例子:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>

struct Base { };

struct Derived1 : public Base { };

struct Derived2 : public Base {
  static Base* Create() { return new Derived2; };
};

struct Derived3 : public Base {
  int value;
  Derived3(int aValue) : value(aValue) { };
  static Base* Create(int aValue) { return new Derived3(aValue); };
};

enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };

int main() {
  std::map< DerivedCreate, boost::function< Base*() > constructor_map;
  constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
  constructor_map[ClassDerived2] = &Derived2::Create;
  constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);

  //now you can call any constructor as so:
  Base* ptr = constructor_map[ClassDerived2]();
};

我可能犯了一些轻微的语法错误,但基本上你应该能够完成上述工作。此外,您拥有多个类模板的事实也不起作用,一旦将它们实例化为具体类(例如 ClassClass),它们就会就像任何其他类一样,上述想法应该仍然有效。

I would say, just construct a std::map that maps the enum to a factory function (boost::function<>). Then you just add one entry for each type that you want, with its corresponding enum. To actually construct the factory functions. You can either have some static Create() function for each class and store a function pointer. Or, you can use Boost.Lambda constructor/destructor functors. Or, you can use Boost.Bind to construct functors that wrap a factory function that requires some number of parameters. Here is an example:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>

struct Base { };

struct Derived1 : public Base { };

struct Derived2 : public Base {
  static Base* Create() { return new Derived2; };
};

struct Derived3 : public Base {
  int value;
  Derived3(int aValue) : value(aValue) { };
  static Base* Create(int aValue) { return new Derived3(aValue); };
};

enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };

int main() {
  std::map< DerivedCreate, boost::function< Base*() > constructor_map;
  constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
  constructor_map[ClassDerived2] = &Derived2::Create;
  constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);

  //now you can call any constructor as so:
  Base* ptr = constructor_map[ClassDerived2]();
};

I might have made some slight syntax mistakes, but basically you should be able make the above work. Also, the fact that you have several class templates plays no role, once they are instantiated to a concrete class (like Class<int> or Class<double>) they are just like any other class, and the above idea should remain valid.

谢绝鈎搭 2024-10-24 23:57:18

扩展您的示例,类似于以下内容:

enum Prec {INT, DOUBLE};

struct Base
{
    virtual ~Base () = 0 {}
};

template<typename T> struct Class : public Base
{
    static Base* create (int flag) {return new Class<T> (flag);}
    Class (int flag) {}
};

typedef Base* (*Creator) (int flag);

Base* createClassInstance (Prec prec)
{
    static const Creator createTab[] = {
        Class<int>::create,
        Class<double>::create
    };

    return createTab[prec] (1);
}

int main (int argc, char* argv[])
{
    Base* c = createClassInstance (DOUBLE);

    return 0;
}

Extending your example, something like the following works:

enum Prec {INT, DOUBLE};

struct Base
{
    virtual ~Base () = 0 {}
};

template<typename T> struct Class : public Base
{
    static Base* create (int flag) {return new Class<T> (flag);}
    Class (int flag) {}
};

typedef Base* (*Creator) (int flag);

Base* createClassInstance (Prec prec)
{
    static const Creator createTab[] = {
        Class<int>::create,
        Class<double>::create
    };

    return createTab[prec] (1);
}

int main (int argc, char* argv[])
{
    Base* c = createClassInstance (DOUBLE);

    return 0;
}
醉生梦死 2024-10-24 23:57:17

实现此类事情的方法有很多种,但听起来您想要创建一个工厂方法数组(或映射)(每个类一个),由 enum 变量索引。每个都调用相关的构造函数,并返回该类型的新对象。

当然,为了使这一点有意义,所有类都必须派生自一个共同的基础。

There are a number of ways of achieving this sort of thing, but it sounds like you want to create an array (or map) of factory methods (one for each class), indexed by the enum variable. Each one calls the relevant constructor, and returns a new object of that type.

Of course, for this to make any sense, all of the classes must derive from a common base.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文