mercredi 30 août 2017

template metaprogramming static member function cannot get const static value of class

I am trying to generate numbers in compile time and tried templates. But when I use constexpr static member variable instead of enum, and in a static member function where I try to push it into a std::vector, the compiler told me the linker was unable to link.

For example, here is a simple program to calculate factorial of n.

#include <iostream>
#include <vector>

template <uint64_t n> struct factorial {
    constexpr static uint64_t value = factorial<n - 1>::value * n;
    static void put(std::vector<uint64_t> &v) {
        factorial<n - 1>::put(v);
        v.push_back(value);
    }
};

template <> struct factorial<0> {
    constexpr static uint64_t value = 1;
    static void put(std::vector<uint64_t> &v) {
        v.push_back(1);
    }
};

int main() {
    using namespace std;
    vector<uint64_t> v;
    factorial<10>::put(v);
    for (auto fact: v)
        cout << fact << endl;
    return 0;
}

This will produce link fail information with both g++ 7.1 and clang 4.0, so I thought it was not a bug. And when I change constexpr static to enum like

template <uint64_t n> struct factorial {
    enum { value = factorial<n - 1>::value * n };
    static void put(std::vector<uint64_t> &v) {
        factorial<n - 1>::put(v);
        v.push_back(value);
    }
};

template <> struct factorial<0> {
    enum { value = 1 };
    static void put(std::vector<uint64_t> &v) {
        v.push_back(1);
    }
};

It compiles and links and runs pretty well.

I am wondering whether C++ standards mentioned about this.

Aucun commentaire:

Enregistrer un commentaire