C++ 模板元编程静态成员函数无法获取类的常量静态值

C++ 模板元编程静态成员函数无法获取类的常量静态值,c++,c++11,templates,template-meta-programming,static-members,C++,C++11,Templates,Template Meta Programming,Static Members,我试图在编译时生成数字,并尝试使用模板。但是,当我使用constexpr static成员变量而不是enum,并且在static成员函数中尝试将其推入std::vector,编译器告诉我链接器无法链接 例如,这里有一个简单的程序来计算n的阶乘 #include <iostream> #include <vector> template <uint64_t n> struct factorial { constexpr static uint64_t

我试图在编译时生成数字,并尝试使用模板。但是,当我使用
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;
}
它编译、链接和运行都非常好

我想知道C++标准是否提到这个问题。

尝试(在第一个例子中)添加< /P>

模板
constexpr uint64_t阶乘::值;

据我所知,这是因为
std::vector::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;
}
#包括
#包括
模板结构阶乘{
constexpr static uint64_t value=factorial::value*n;
静态空放(标准::向量&v){
阶乘:put(v);
自动vcpy=value;//***此处***
v、 推回(vcpy);
}
};
模板结构阶乘{
constexpr static uint64_t value=1;
静态空放(标准::向量&v){
v、 推回(1);
}
};
int main(){
使用名称空间std;
向量v;
阶乘:put(v);
用于(自动事实:v)

是的,它可以工作。而且有问题的代码也使用
-std=c++17
编译。还有一个问题:为什么
enum
可以工作,似乎enum也从来没有定义过。@xris因为enum不是
静态常量
值-它是一个r值表达式。因此在使用时会生成一个实例。
template <uint64_t n>
constexpr uint64_t factorial<n>::value;
#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;
}