Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deduction of the function

Let's say we have a class template like this:

template<typename F>
class A
{
public:
  template<typename... Args>
  A(F f, Args... args)
  { /* Do something... */ }
};

And now I want to use it in some way like this one:

A<int(int)> a(::close, 1);

Now the question: is there any way to omit the <int(int)> because a compiler can know this information for the ::close? There is no need to save the "design" of the template.

As for concrete task, I need to design a template of a class. Objects of this class could take a function and parameters for this function at construction time and call this function later.

like image 965
Serge Roussak Avatar asked Jul 06 '16 16:07

Serge Roussak


Video Answer


3 Answers

No, you (currently) cannot. The standard way of doing this is by creating "make_like" function (such as make_pair, make_optional ...):

template<typename F, typename... Args>
A<std::decay_t<F>> make_A (F &&f, Args&&... args) {
    return {std::forward<F>(f), std::forward<Args>(args)...};
}

C++17 will introduce template argument deduction for class which will allow you to do exactly what you want (see also Barry's answer below).

like image 149
Holt Avatar answered Oct 17 '22 06:10

Holt


Thanks to the adoption of template parameter deduction for constructors, in C++17, you'll be able to just write:

A a(::close, 1);

Before that, you'll just need to write a factory to do the deduction for you:

template <class F, class... Args>
A<std::decay_t<F>> make_a(F&& f, Args&&... args) {
    return {std::forward<F>(f), std::forward<Args>(args)...};
}

auto a = make_a(::close, 1);

This is a little verbose, but at least you don't need to worry about efficiency - there will be no copies made here thanks to RVO.

like image 33
Barry Avatar answered Oct 17 '22 05:10

Barry


You cannot omit the arguments of a template class, unless they are defaulted. What you can do is have a maker function which deduces the argument and forwards this argument to the template class, returning an object of the appropriate instantiation.

template<typename F, typename... Args>
A<F> make_A(F f, Args&&... args) {
    return A<F>(f, std::forward<Args>(args)...);
}
like image 11
Benjamin Lindley Avatar answered Oct 17 '22 06:10

Benjamin Lindley