2017-02-09 100 views
6

通常情况下,如果我有一个FooBar,我会做这样的事情:是否可以创建一个可用于创建任何类的“新”实例的泛型方法或类?

Foo* foo = new Foo(); 

Bar* bar = new Bar(2,3,5); 

是否有使用模板或宏的方式,我可以构建一个功能,这样我可以这样做:

Foo* foo = MyAwesomeFunc(Foo); 
Bar* bar = MyAwesomeFunc(Bar,2,3,5); 

MyAwesomeFunc的实际方法签名对我来说并不重要。

FooBar不需要以任何可能的方式有关,并可能有完全不同的构造。此外,我可能要在将来支持任意数量的类,而不必实际修改代码MyAwesomeFunc

这可能吗?一个简单的办法是同时拥有Foo和一些类型Bar继承,说Baz,并有重载方法返回一个Baz,你投回到FooBar ...

Baz* MyAwesomeFunc(){ 
    return new Foo(); 
} 

Baz* MyAwesomeFunc(int a,int b,int c){ 
    return new Bar(a,b,c); 
} 

但这里的问题是你会写:支持

  • 和各种构造签名的

    1. 为每个类的方法。

    的目标,是写一个类,方法,或宏,在这里我们可以 调用一个函数(传递的任何参数),但调用传入的对象右侧 构造。这可能吗 ?

    这个问题的目的是简单地探讨是否有可能在C++中做这样的事情。请不要提出共同的指针,独特的指针,使用新的缺陷,因为这是脱离主题。

    编辑:我想只使用STL,并避免使用像升压....

  • +1

    查看'boost :: factory' – Ari0nhh

    +0

    @Ar i0nhh谢谢阿里 - 任何方式轻松地做到这一点,而无需使用Boost? –

    +3

    Pre C++ 11,“Perfect Forwarding”和“Variadic Templates”不存在。 'Boost'为社区提供了制作愚蠢强大代码的工具,'boost :: factory'是事实上的工厂,它被完美的转发和可变模板所取代。 – Gambit

    回答

    8

    由于C++ 11你可以用variadic templateperfect forward做到这一点。例如。编写一个模板函数,它完美地将其参数转发给模板参数指定的类型的对象的构造函数。

    template <typename T, typename... Ts> 
    T* MyAwesomeFunc(Ts&&... params){ 
        return new T(std::forward<Ts>(params)...); 
    } 
    

    然后用它作为

    Foo* foo = MyAwesomeFunc<Foo>(); 
    Bar* bar = MyAwesomeFunc<Bar>(2,3,5); 
    
    +1

    如果您尝试创建一个Bar,但没有所有必需的参数,会发生什么情况? –

    +1

    您可以使用'type_traits'中的'std :: is_constructible'。看到我的答案。 – Gambit

    +5

    @John,编译器错误。它从外部看起来并不完美,但是有办法解决这个问题(概念和模拟)。 – chris

    8

    是的,你可以使用模板和C++ 11的 “完美转发”:

    #include <type_traits> 
    #include <utility> 
    
    template<typename T, typename... Args> 
    T* createNew(Args&&... args) 
    { 
        static_assert(std::is_constructible<T, Args...>::value, "T is not constructible with these arguments"); 
        return new T(std::forward<Args>(args)...); 
    } 
    

    或者,你可以看看C++ 11的std::make_unique和“智能指针”What is a smart pointer and when should I use one?

    +0

    如果会出现编译器错误,那为什么要用std :: is_constructible? –

    +4

    因为你可以设置自己的消息,它不会在可怕的编译错误中丢失。 – Gambit

    相关问题