Reputation: 365
Is it possible for a class method to be called somehow and automatically deduce templated arguments?
I'm trying to create an object with a create class method that calls a private constructor. I'm doing so in order to make sure the created instance is allocated on the heap.
The class in templated and I'd like the user not having to know the types (can be complicated with rvalue reference to lambdas).
Here's a toy example of what I'd like to achieve (I know the constructor is public here):
template <typename T>
class hello
{
public:
hello(T t){}
static std::shared_ptr<hello<T>> create(T t)
{
return std::make_shared<hello<T>>(t);
}
};
template <typename T>
auto create_hello(T t)
{
return std::make_shared<hello<T>>(t);
}
void test_hello()
{
auto h1 = hello(3); // ok
auto h2 = std::make_shared<hello<int>>(3); // ok
auto h3 = create_hello(3); // ok
auto h4 = hello<int>::create(3); // ok
auto h5 = hello::create(3); // Compile error: 'hello' is not a class, namespace, or enumeration
}
Is there a way to invoke the static create method and having the template parameters automatically deduced like when calling the constructor directly?
Upvotes: 0
Views: 1116
Reputation: 917
You are mixing up two different things:
Whereas auto h1 = hello(3)
works since, it makes use of constructor template deduction, but since create
is not a constructor, the template parameter cannot be deduced from the parameter.
To solve that, you have to source out your create
function:
template <class U>
static std::shared_ptr<hello<T>> make_hello(U t)
{
return std::make_shared<hello<U>>(t);
}
Edit: If you want have the constructor private, just friend the function:
template <typename T>
class hello
{
hello(T t){}
public:
template <class U>
friend std::shared_ptr<hello<U>> make_hello(U t);
};
template <class T>
std::shared_ptr<hello<T>> make_hello(T t)
{
return std::shared_ptr<hello<T>>(new hello<T>(t));
}
Upvotes: 1
Reputation: 60440
No, this is not currently possible. There are only a few contexts in which the template arguments of a class can be deduced:
any declaration that specifies initialization of a variable and variable template, e.g.
hello h(3);
new-expressions, e.g.
auto h = new hello{3};
function-style cast expressions, e.g.
auto h = hello(3);
and from c++20:
the type of a non-type template parameter
In this expression:
hello::create(3)
the template argument needs to be deduced, since it's not specified, but none of the above contexts apply, since there is no rule for deduction of a template parameter from the invocation of a static member function.
Upvotes: 1