4

I was trying to use variable templates the same way I use some other templates, for example: we already know how to calculate a Fibonacci number or the power of a number using metaprogramming with template objects wrapping a static value or a enum value.

So, the first thing I did was trying to specialize a template variable, and it works as expected:

template <std::size_t VALUE> std::size_t value       = VALUE;
template <>                  std::size_t value<666u> = 1u;

std::cout << value<0u> << '\n';   // "0" as expected
std::cout << value<1u> << '\n';   // "1" as expected
std::cout << value<2u> << '\n';   // "2" as expected
std::cout << value<666u> << '\n'; // "1" as expected!!

Knowing that variable template specialization is possible I've tried to do a variable template Fibonacci number:

template <std::size_t ITERATION>
std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
template <> std::size_t fibonacci<1u> = 1u;
template <> std::size_t fibonacci<0u> = 0u;

int main()
{
    std::cout << fibonacci<5> << '\n'; // "8" expected;
    return 0;
}

The error i get from Wandbox is the following:

error: expected primary-expression before ';' token
template <std::size_t ITERATION> std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
                                                                                                              ^

I don't know what I'm doing wrong nor understand the error. I'm guessing that the error could be releated with the fact that the variable template isnt yet defined while I'm already using it so I'm wondering if is it even possible to achieve my goal with variable templates.

Any hint?

Thanks a lot.

Community
  • 1
  • 1
PaperBirdMaster
  • 12,806
  • 9
  • 48
  • 94

1 Answers1

2

My guess is that compilers do not yet implement variable templates properly. For instance, clang 3.7.0 compiles your code but (with a small bug fix: fibonacci<0u> = 1u) outputs 0 instead of 8 for fibonacci<5>.

However, if we do

std::cout << fibonacci<0> << '\n'; // "1" expected;
std::cout << fibonacci<1> << '\n'; // "1" expected;
std::cout << fibonacci<2> << '\n'; // "2" expected;
std::cout << fibonacci<3> << '\n'; // "3" expected;
std::cout << fibonacci<4> << '\n'; // "5" expected;
std::cout << fibonacci<5> << '\n'; // "8" expected;

then we get the expected results. Weird!

Update Since function templates are more mature than variable templates, the following is a workaround:

template <std::size_t ITERATION>
constexpr std::size_t get_fibonacci()
{
    return get_fibonacci<ITERATION - 1u>() + get_fibonacci<ITERATION - 2u>();
}

template <>
constexpr std::size_t get_fibonacci<0u>() {
    return 1u;
}

template <>
constexpr std::size_t get_fibonacci<1u>() {
    return 1u;
}

template <std::size_t ITERATION>
std::size_t fibonacci = get_fibonacci<ITERATION>();
Cassio Neri
  • 19,583
  • 7
  • 46
  • 68
  • Well, the expected results can only be achieved with correct code; if I had an error or a typo there's no way to get an `8` for the 5th Fibonacci number ;) anyway, it seems that my issue is releated to how the compiler implements VTs so it's a relief that the code is expected to work. Many thanks! – PaperBirdMaster Mar 18 '15 at 10:44
  • I'd blame the standard, not the compiler vendors themselves – Piotr Skotnicki Mar 18 '15 at 10:56
  • 1
    @PiotrS. It turns out that most compiler vendors are members of the Standard's committee. My point is that probably this is just a question of time until the implementations get this right. – Cassio Neri Mar 18 '15 at 11:02
  • @CassioNeri I've noticed that making the template and its specializations `constexpr` it works as expected. I'm guessin that if you use `fibonacci<5>` all alone the compiler doesn't compute the previous values (unless it is a `constexpr`) and thus it returns `0`. – PaperBirdMaster Mar 20 '15 at 08:30
  • 1
    @PaperBirdMaster Interesting! I agree that the compiler is not recursively instantiating the template unless it's `constexpr`. I don't know whether this is intended behavior or compiler bug. – Cassio Neri Mar 20 '15 at 09:35