3

Need to create variadic template<T> function with different arg types that will call constructor of T with given arguments, sort of like when creating a thread but reverse (when creating a thread, its constructor calls function at given funct pointer).

So in pseudo code it should look something like this

template<typename T>
T* CreateNew( ARGS ) {
    return new T( ARGS );    //Constructor Gets Same Arguments That Were 
}                            //Passed To The Function

Want this to behave like when creating threads, when they call functions with their arguments that are of different types (which I am unsure how to achive).

Quentin
  • 62,093
  • 7
  • 131
  • 191

2 Answers2

3

Its not entirely clear to me but I think you want to look up variadic templates, e.g.:

template <typename T, typename... Args>
T* CreateNew(Args... args) {
    return new T(args...);
}

Adding Example:

#include <iostream>

class A {
    public:
    A(int a){
        std::cout<<__PRETTY_FUNCTION__<<std::endl;
    }
    A(std::string a){
        std::cout<<__PRETTY_FUNCTION__<<std::endl;
    }
    A(int a,std::string b){
        std::cout<<__PRETTY_FUNCTION__<<std::endl;
    }
};

template<typename T, typename... Args>
T* create(Args... args){
    return new T(args...);
}

int main(){
    A b(1);
    A c("a");
    A d(1,"a");
    A* bp = create<A>(1);
    A* cp = create<A>("a");
    A* dp = create<A>(1,"a");
    // This code leaks
    return 0;   
}

Note that because the changes are kept as minimal as possible, we still return a T* here as the original code. Most of the time, this is not a good idea since ownership is passed via raw pointers. Therefore, as suggested by the comments, you might want to use a std::unique_ptr, which would make your CreateNew function basically equivalent to std::make_unique.

tos-1
  • 135
  • 6
  • For further reading: [Parameter packs](https://en.cppreference.com/w/cpp/language/parameter_pack) – Lukas-T Jul 12 '19 at 07:23
  • And using `std::unique_ptr` instead of raw owning pointer would be even better (and allow to avoid current memory leaks). – Jarod42 Jul 12 '19 at 08:58
  • @Jarod42 your're totally right, thanks for pointing it out. Since I want to keep the changes to OT's code minimal, I just added a comment in the example and a paragraph about using `std::unique_ptr` and `std::make_unique`. – tos-1 Jul 12 '19 at 17:14
  • 1
    This implementation is broken as it does not perfectly forward `args...`. – Vittorio Romeo Jul 12 '19 at 17:31
2

The correct way to write this function is

template <typename T, typename... Args>
T* CreateNew(Args&&... args) {
    return new T(std::forward<Args>(args)...);
}

Without the forwarding reference Args&& and without std::forward, the original value categories of the passed arguments will not be propagated to T's constructor, causing potential performance and semantic problems.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416