Reputation: 109
I want to be able to create a new object of type T as illustrated in this code snippet.
template<typename T, typename Arg1, typename Arg2>
void ManageDevice(T& device, Arg1 arg1, Arg2 arg2)
{
auto newDevice = new T{ arg1, arg2 };
// ... Perform more operations on newDevice
}
I am currently using the function like this:
CertainClass* device;
ManageDevice(device, arg1, arg2);
The compiler returns the error: Cannot convert from "initializer list" to "class of T*".
I also tried:
auto newDevice = new decltype(device){ arg1, arg2 };
And got the following error:
Error C2464 'class of T*&': cannot use 'new' to allocate a reference
So I removed the reference with this:
using DeviceType = std::remove_reference<decltype(device)>::type;
auto newDevice = new DeviceType{ arg1, arg2 };
And I got the first error message again.
Questions:
Upvotes: 2
Views: 1042
Reputation: 62583
Your factual and template parameters do not match. When the template is written as
template<typename T>
void foo(T& t);
and called with
D* d;
foo(d);
The type of T
inside template is going to be D*
. Now, if you try
x = new D*{'a', 'b', 'c'};
You will get an obvious compilation error, as there is no (pseudo) constructor for pointer which takes those arguments.
To achieve your goals, you should use
template<typename T, typename Arg1, typename Arg2>
void ManageDevice(T*& device, Arg1 arg1, Arg2 arg2)...
In this case, when called with
Device* device;
ManageDevice(device...);
The actual T
inside template would be deduced as Device
.
This was written in assumption that you use device
as an output parameter. If I guessed, correctly, a better option is to actually return the value, rather than use output parameter:
template<typename T, typename Arg1, typename Arg2>
T* ManageDevice(Arg1 arg1, Arg2 arg2) {
...
return new_device;
}
Then, you can call it as
auto* device = ManageDevice<Device>(a, b);
And while on it, replace T* with unique_ptr<T>
and new
with std::make_unique
.
Upvotes: 3
Reputation: 37587
It should be ManageDevice(*device, arg1, arg2);
so T
is deduced to be CertainClass
so constructor invocation new T{
will be well-formed. Or, if you are passing a pointer (which probably not a good idea), use std::remove_pointer
to get object type from T
:
using DeviceType = typename ::std::remove_pointer<T>::type;
Upvotes: 2