我遇到了一个模板结构的静态constexpr成员的问题。代码编译但我得到链接错误。这就是我想要做的事情:
template<int n>
struct Test {
static constexpr auto invoke = make_tuple(2, "test", 3.4);
};
template<typename T>
void test(T&& t) {
cout << t << endl;
}
int main() {
test(get<0>(Test<2>::invoke));
return 0;
}
我发现链接错误,所以我尝试了这个:
template<int n>
struct Test {
static constexpr auto invoke = make_tuple(2, "test", 3.4);
};
// declare it outside the class
template<int n>
constexpr decltype(Test<n>::invoke) Test<n>::invoke;
template<typename T>
void test(T&& t) {
cout << t << endl;
}
int main() {
test(get<0>(Test<2>::invoke));
return 0;
}
但我得到了这个奇怪的错误:
error: redefinition of 'invoke' with a different type: 'const decltype(Test<n>::invoke)' vs 'const std::tuple<int, const char *, double>'
不同类型? 显然,非模板版本的工作正常:
struct Test {
static constexpr auto invoke = make_tuple(2, "test", 3.4);
};
constexpr decltype(Test::invoke) Test::invoke;
template<typename T>
void test(T&& t) {
cout << t << endl;
}
int main() {
test(get<0>(Test::invoke));
return 0;
}
如何让模板版本正常运行?非常感谢你
答案 0 :(得分:3)
看起来你正在遇到一个有趣的角落案例,这个案例包含在decl bug报告 Static constexpr definitions used inside template中,其中包含以下示例,其中包含与您类似的错误:
理查德史密斯的回复如下:这编译很好,但是当我创建A类时,这样的模板:
struct L { void operator()() const {} }; template<class X> struct A { static constexpr auto F = L(); }; template<class X> constexpr decltype(A<X>::F) A<X>::F; int main() { A<void>::F(); return 0; }
Clang崩溃,如果我将F的定义行更改为:
template<class X> constexpr typename std::remove_const<decltype(A<X>::F)>::type A<X>::F;
然后clang产生了这个错误:
error: redefinition of 'F' with a different type constexpr typename std::remove_const<decltype(A<X>::F)>::type A<X>::F; ^ note: previous definition is here static constexpr auto F = L(); ^
此错误是正确的。 &#39; constexpr&#39;和&#39;汽车&#39;这里是红色的鲱鱼。 减少测试用例:
template<class X> struct A { static int F; }; template<class X> decltype(A<X>::F) A<X>::F;
Per C ++ 11 [temp.type] p2,&#34;如果表达式e涉及模板 参数,decltype(e)表示唯一的依赖类型。&#34;因此 A :: F的类型与模板中的类型不匹配。
C ++ 14草案的完整引用如下:
如果表达式e涉及模板参数,则decltype(e)表示 独特的依赖类型。两个这样的decltype-specifiers指的是 只有当它们的表达式相同时才是相同的类型(14.5.6.1)。 [ 注意: 但是,它可以是别名,例如,通过typedef-name。 - 后注]
我能看到的唯一明显的方法是:
template<int n>
constexpr decltype(make_tuple(2, "test", 3.4)) Test<n>::invoke;
错误报告中没有提供任何解决方法。
答案 1 :(得分:2)
如何让模板版本正常运行?
FWIW,您的方法在我的桌面上运行正常,它使用g ++ 4.8.4。
您可以使用:
disable: function(e) {
$.ajax({
context: this
, type:"POST"
, url:url
, success: function() {
console.log(this);
}
, error: function() {
console.log(this)
}
})
}
以下内容也适用于我的桌面:
template<int n>
constexpr decltype(make_tuple(2, "test", 3.4)) Test<n>::invoke;