模板元编程静态成员函数无法获取 class 的 const 静态值
template metaprogramming static member function cannot get const static value of class
我正在尝试在编译时生成数字并尝试使用模板。但是当我使用 constexpr static
成员变量而不是 enum
时,在 static
成员函数中我试图将它推入 std::vector
,编译器告诉我 linker 无法 link.
例如,这里有一个计算 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 中产生 link 失败信息,所以我认为这不是错误。当我将 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);
}
};
它编译 link 并且运行良好。
我想知道 C++ 标准是否提到了这一点。
尝试(在您的第一个示例中)添加
template <uint64_t n>
constexpr uint64_t factorial<n>::value;
据我所知这是因为 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;
}
我正在尝试在编译时生成数字并尝试使用模板。但是当我使用 constexpr static
成员变量而不是 enum
时,在 static
成员函数中我试图将它推入 std::vector
,编译器告诉我 linker 无法 link.
例如,这里有一个计算 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 中产生 link 失败信息,所以我认为这不是错误。当我将 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);
}
};
它编译 link 并且运行良好。
我想知道 C++ 标准是否提到了这一点。
尝试(在您的第一个示例中)添加
template <uint64_t n>
constexpr uint64_t factorial<n>::value;
据我所知这是因为 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;
}