1

I have been lately been learning template meta programming in C++. After checking calculating factorials example, was wondering if the same thing could be done only with template functions rather than template classes. My first attempt is shown below

#include <stdio.h>
#include <iostream>

using namespace std;

template <int t>
int multiply(t)
{
    return (multiply(t-1) * t);
}

template <>
int multiply(1)
{
    return 1;
}

int main () {
    cout << multiply(5) << endl;
    return 0;

}

But I get the following compiler errors

temp.cpp:7: error: template declaration of 'int multiply'
temp.cpp:14: error: expected ';' before '{' token
temp.cpp: In function 'int main()':
temp.cpp:19: error: 'multiply' was not declared in this scope

Can I do such template metaprogramming using template functions? Is this allowed ?

6
  • 3
    function declarations need to declare the parameter type not the parameter value. int multiply(t) doesnt make sense, whether template or not Commented May 5, 2017 at 7:20
  • please note that the recursion in the example you linked is about types (ie happens at compile time), while the recursion you are trying to do here is about calling functions (ie it happens at runtime). Maybe there is a way to use template functions, but you dont need a template when you use recursive runtime calls to compute the factorial Commented May 5, 2017 at 7:27
  • is there a way to use template functions to do this in compile time as in the example I've linked? Commented May 5, 2017 at 7:37
  • For dumb compilers and/or non-optimized debug builds, the contexpr function approach can have interesting effects on binary size compared to the template approach. Commented May 5, 2017 at 8:05
  • @You: With correct usage, it does it job correctly Demo Commented May 5, 2017 at 8:49

1 Answer 1

2

As stated by tobi303 in the comments, using just (t) as a parameter list of a function, where t is not a type name, makes no sense.

Since int t is a template parameter, not a regular parameter, it should only be present in the template parameters list (between the < and > angle brackets), and not in the function parameters list (between the ( and ) parenthesis). Template parameters must also be passed as such, i.e. multiply<5>() instead of multiply(5) in your code.

You could use something like:

#include <iostream>

using namespace std;

template <int t>
constexpr int multiply() {
    return multiply<t - 1>() * t;
}

template <>
constexpr int multiply<1>() {
    return 1;
}

int main () {
    cout << multiply<5>() << endl;
    return 0;
}

Note also that I've added constexpr (C++11 and later) to always be able to evaluate these functions at compile-time. However, the compiler is not forced to evaluate these at compile-time instead of run-time, and you might still end up with the run-time overhead.

Sign up to request clarification or add additional context in comments.

4 Comments

constexpr does not force evaluation at compile time.
To force compile time evaluation: constexpr auto fact5 = multiply<5>(); std::cout << fact5 << std::endl;
@Jarod42 What guarantees that?
As constexpr variable should be known at compile time, its evaluation is also done at compile time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.