7

我想在头文件中转发声明变量模板,然后在单独的编译单元中进行实际实例化。

我被引导相信 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;
                     ^
4

2 回答 2

2

我认为你在正确的轨道上。

诀窍是:在任何一个翻译单元中,不要在您的专业化之前实例化模板。

例如:

// 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

更新

TC 在下面的评论中指出,专业化需要在首次使用之前声明,所以我已经更新了上面的“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>;
             ^~~~~~

我搜索了标准和核心问题列表,但找不到任何表明一个编译器或另一个是正确的。如果有人确实看到了此类证据,我很乐意将其包含在此答案中。

于 2016-01-24T17:55:59.320 回答
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

于 2021-04-11T17:38:11.747 回答