user1912594
user1912594

Reputation: 365

c++ class method auto template parameter automatic deduction

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

Answers (2)

JulianW
JulianW

Reputation: 917

You are mixing up two different things:

  1. Constructor template deduction and
  2. function template deduction.

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

cigien
cigien

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

Related Questions