Join the Stack Overflow Community
Stack Overflow is a community of 6.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Normally, if I have a Foo, or a Bar, I would do something like:

Foo* foo = new Foo();

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

Is there a way using templates or macros, that I can construct a function, such that I can do something like:

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

The actual method signature of MyAwesomeFunc is not important to me.

Foo and Bar need not be related in any possible way, and may have completely different constructors. Additionally, I may want to support any number of classes in the future without having to actually modify the code of MyAwesomeFunc

Is this possible ? A simple way would be to have both Foo and Bar inherit from some type, say Baz, and have overloaded methods return a Baz, which you cast back to Foo or Bar...

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

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

But the problems here is you would have to write:

  1. a method for each class supported
  2. and for each kind of constructor signature.

The goal, is to write a single class, method, or macro, where we can call one function (and pass it any arguments), but call the right constructor of the passed in object. Is this possible ?

The purpose of this question is to simply explore if it is possible to do something like this in C++. Please do not bring up shared pointers, unique pointers, the pitfalls of using new, as that is off topic.

EDIT: I would like to use only the STL, and avoid using things like Boost....

share|improve this question
1  
See boost::factory – Ari0nhh 5 hours ago
    
@Ari0nhh Thanks Ari - any way to do this easily without using Boost ? – John 5 hours ago
2  
Pre C++11, "Perfect Forwarding" and "Variadic Templates" didnt exist. Boost supplied the community with the tools to make stupidly powerful code and boost::factory was the defacto factory which has been superceeded by perfect forwarding and variadic templates. – Tyler Duffus 5 hours ago
up vote 6 down vote accepted

Since C++11 you can do it with variadic template and perfect forward. E.g. write a template function, which perfect forwards its parameters to the constructor of the object with type specified by template parameter.

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

Then use it as

Foo* foo = MyAwesomeFunc<Foo>();
Bar* bar = MyAwesomeFunc<Bar>(2,3,5); 
share|improve this answer
1  
What happens if you try to create a Bar, without all the required arguments ? – John 5 hours ago
1  
You can use std::is_constructible from type_traits. See my answer. – Tyler Duffus 5 hours ago
4  
@John, Compiler error. It won't look perfect from the outside, but there are ways to fix that (concepts, and emulation thereof). – chris 5 hours ago
2  
@John If the arguments provided don't match the constructor of the object, then you'll get a compiler error; it's same as when you write new Bar(something);. – songyuanyao 5 hours ago

Yes you can use templates and C++11's "Perfect Forwarding":

#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)...);
}

Alternatively, you could check out C++11's std::make_unique and "Smart Pointers" What is a smart pointer and when should I use one?

share|improve this answer
    
If there will be a compiler error, then why use std::is_constructible ? – John 5 hours ago
3  
Because you can set your own message and it wont be lost in horrible compiler errors. – Tyler Duffus 5 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.