模板元编程静态成员函数无法获得类的静态静态值

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

本文关键字:静态 编程 静态成员 函数      更新时间:2023-10-16

我正在尝试在编译时间和尝试模板中生成数字。但是,当我使用constexpr static成员变量而不是enum,然后在static成员函数中尝试将其推入std::vector时,编译器告诉我链接器无法链接。

例如,这是一个简单的程序,用于计算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;
}

这将与G 7.1和Clang 4.0同时产生链接失败信息,因此我认为这不是错误。当我将constexpr static更改为 enum

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);
    }
};

它编译和链接并运行良好。

我想知道是否提到了C 标准。

据我所知,这是因为 std::vector<T>::push_back()具有签名
void push_back(V const&)

因此,正在提到价值。

因此,它必须具有一个地址,这不是因为它从未定义(尽管对我来说似乎有点不合逻辑) - 也许这是在C 17中固定的?

可以通过取副本并推动它来编译:

#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);
        auto vcpy = value;   // *** HERE ***
        v.push_back(vcpy);
    }
};
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;
}

尝试(在第一个示例中)添加

template <uint64_t n>
constexpr uint64_t factorial<n>::value;