1

I am new to c++ and need help with metaprogramming. I have checked out the enum example wherein the call factorial<4>::value yields 24.

What I need is a modification to the code so that factorial<4>() returns 24. Have been trying it for quite some time now and do not know how to exactly search for it on the internet too. Any help would be much appreciated. Thank you !

Here is what I have at the moment:

template <int N> struct factorial { enum { value = N * factorial<N - 1>() }; }; template <> struct factorial<0> { enum { value = 1 }; }; 
2
  • You're going to need a function, functor, or some other callable object. Start with that. Commented Jun 16, 2014 at 0:14
  • Thanks @ghostofstandardspast , I'll look into it. Never worked with functors before. Commented Jun 16, 2014 at 0:24

2 Answers 2

4

You can use a constexpr function:

template<int N> constexpr int factorial() { return N * factorial<N - 1>(); } template<> constexpr int factorial<0>() { return 1; } 

Live demo

This will allow you to call:

factorial<4>(); 

and get 24 as a returned value.


Alternatively you can use the implicit conversion operator operator int() to perform an implicit conversion, of the struct to int:

template<int N> struct factorial { static const int value = N * factorial<N-1>::value; operator int() { return value; } }; template<> struct factorial<0> { static const int value = 1; operator int() { return value; } }; 

Live demo

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

10 Comments

Thanks a lot @Jefffrey. But I am not able to understand the error (never used constexpr) : expected constructor, destructor or type conversion before 'int'
@Noob What code are you running? Paste it here and then click "Share" on the bottom right. Moreover, if you click on "Live demo", you can see the correct usage of the given solution.
@Noob, constexpr is a C++11 feature. Make sure you have C++11 enabled.
@Noob Yeah, that might be it. You can use the -std=c++11 compiler flag to enable C++11.
@jeffrey: "not possible defclaring factorial as a struct... just have to add constexpr operator int() const { return value; }` members - see ideone.com/bFVyMR
|
4

To just use the function call like a function call, you need to use constexpr (a new addition to C++11). Note that when you do use this, you do not need to use a template at all though. Though there are some limitations, the basic syntax is that of a normal function:

int constexpr fact(int x) { return x == 0 ? 1 : x * fact(x - 1); } 

This is still computed at compile time though. For example, if you wanted to use it to specify the size of an array, you could do so:

int main(){ int array[fact(5)]; } 

Likewise, you can use such a result as a case in a switch statement:

#include <iostream> #include <cstdlib> int constexpr fact(int x) { return x == 0 ? 1 : x * fact(x - 1); } int main(int agc, char **argv){ switch (std::atoi(argv[1])) { case fact(1) : case fact(2): case fact(3): case fact(4): case fact(5): std::cout << "You entered a perfect factorial"; break; default: std::cout << "I'm not sure about that"; } } 

[compiled/tested with gcc 4.8.1]

1 Comment

Pedantic remark concerning "This is still computed at compile time though": unless the compiler is forced to evaluate the function call at compile-time (as it is in your example), there is no guarantee that the expression will indeed be evaluated at compile-time.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.