我想在头文件中转发声明变量模板,然后在单独的编译单元中实际实例化。
我被认为C ++ 14变量模板的运行方式与静态类变量非常相似。不幸的是,这似乎并非如此,它阻止我向前声明我的变量模板。
template <typename T> struct Variable {
static int variable;
};
template <typename T>
extern int variable;
int main() {
(void) Variable<char>::variable;
// (void) variable<char>; // <-- line 10
}
template <> int Variable<char>::variable = 42;
template <> int variable<char> = 23;
上面的代码示例在GCC下编译并按原样运行。但是,取消注释第10行会产生编译时错误:
specialization of 'variable<char>' after instantiation
template <> int variable<char> = 23;
^
答案 0 :(得分:1)
我认为你走在正确的轨道上。
诀窍是:在任何一个翻译单元中,不要在专业化之前实例化模板。
例如:
// test.h
#ifndef TEST_H
#define TEST_H
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#endif // TEST_H
然后:
// test2.cpp
#include "test.h"
template <> int variable<char> = 23;
template <> int variable<int> = 24;
最后:
// test.cpp
#include "test.h"
#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
对我来说这是输出:
23
24
<强>更新强>
T.C。在下面的评论中指出专业化需要在首次使用之前声明,所以我已经更新了上面的“test.h”来做到这一点。
更新2
似乎存在一些实施差异。 clang似乎处理了这个罚款:
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
template <> int variable<char> = 23;
template <> int variable<int> = 24;
http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi
然而gcc给出错误:
prog.cc:4:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<char>;
^~~~~~
prog.cc:5:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<int>;
^~~~~~
我搜索了标准和核心问题列表,我找不到任何指示一个编译器或另一个是正确的。如果有人确实看到了这样的证据,我很乐意将其包含在这个答案中。
答案 1 :(得分:0)
我也遇到了同样的问题,经过一番研究找到了解决方案。
TL;DR:实例化,而不是专门化模板。使用 extern template int variable<int>
,而不是 template extern int variable<int>
。
似乎 extern template
是 C++ 中的一个特性,它使模板函数成为外部符号,而不是每次都编译。通常这是加快编译时间的一个技巧,但在我们的例子中它很适合。
所以整个解决方案是:
变量.h
// Declare a template variable.
template <typename T>
extern int variable;
// Implicit instantiation of variable declaration.
extern template int variable<int>;
变量.cpp
// Define a template variable.
template <typename T>
int variable = 42;
// Implicit instantiation of variable definition.
template int variable<int>;
我没有尝试过其他编译器,但它适用于 clang 10。
我为 extern template
找到了一些 reference。