When are template arguments required in C++?

Viewed 667

I am curious as to when template arguments are required in C++.

For example, let's define a class as

template<typename T> class Add {
    T value;
public:
    Add(T value) : value(value){};

    T operator() (T valrhs){
        return value + valrhs; 
    }
};

If we wanted to create an object of type Add using double, we would need to define it as follows to not get errors,

Add<double> add5 = Add<double>(5.0);

Lets now consider a function defined as follows,

template<typename T, typename Function> T doOperation (T data, Function f){
    return f(data);
}

In code, if one was to make a call to doOperation, no template arguments would be needed. For example,

std::cout << doOperation(5.0, add5);

would output 10. Why is it that doOperation does not require template arguments but the defining add5 required template arguments?

Also, would there be any way to define this using function pointers. I have been stuck trying to figure out how to pass a functor like this using a function pointer as a parameter variable rather than a second template argument.

Thanks, any help is appreciated.

3 Answers

In this code

std::cout << doOperation(5.0, add5);

The compiler does function-template argument deduction.

In this line

Add<double> add5 = Add<double>(5.0);

you need to provide the template arguments since the compiler won't do class-template argument deduction.

However, from c++17, the compiler will do class-template argument deduction, and then this compiles just fine

Add add5(5.0);

You can provide the deduction guide explicitly as well, since that may be needed in some cases

template<typename T>  Add(T) -> Add<T>;

On a side-note, your class Add looks like it could be replaced by a function-template that returns a lambda.

template<typename T>
auto Add (T value) { 
    return [value] (T valrhs) { 
        return value + valrhs; 
    }; 
}

The usage would then look like

auto add5 = Add(5.0);
std::cout << doOperation(5.0, add5);

When are template arguments required in C++?

Template arguments must be supplied explicitly when they cannot be deduced - unless the parameter has a default argument.

Template argument of a function template may be deduced from a non-template arguments. Template argument of a class template can be deduced from arguments of the constructor if the template class has a deduction guide (which may be implicitly generated).

Why is it that doOperation does not require template arguments

Because the template argument is deduced from the non-template argument for data.

but the defining add5 required template arguments?

Actually, add5 doesn't require explicit template arguments. Following would work:

Add add5(5.0);

... unless you use an old version of C++ that didn't have template deduction guides (which were introduced in C++17).

Since C++17 there is a class-template argument deduction, as was mentioned above. But you must be steady about it, because it may produce the unwanted result.

Add a(5.0); // the type Add<double> is deduced

Add b(5); // the type Add<int> is deduced, which may be unwanted, if you need Add<double> 
          // if so you must specify the desired type
Related