阅读C++ Templates: The Complete Guide并说明
请注意,无法声明模板 在一个函数
它不对书中的任何其他章节或外部资源给出解释和/或交叉引用。
有人可以帮忙解释一下。可能它会在本书后面解释,但还没有。如果先前解释过,我一定错过了它。
示例:
int main()
{
class DummyClass // This compiles ok
{
int object;
};
template <typename T> // compile error "expected primary-expression before "template""
class DummyTemplate
{
T object;
};
return 0;
}
我也不明白gcc的错误信息。错误消息显示:
expected primary-expression before "template"
答案 0 :(得分:37)
问题可能与实现模板的历史方式有关:早期实现技术(以及今天仍在使用的一些技术)要求模板中的所有符号都具有外部链接。 (实例化是通过在单独的文件中生成等效代码来完成的。)函数内定义的名称永远不会有链接,也不能在定义它们的范围之外引用。
答案 1 :(得分:3)
这意味着您无法执行以下操作
void foo()
{
template <typename T> //Error
T something;
}
模板声明仅允许在全局,命名空间或类范围内使用。 :)
背后的原因是什么?
这是不允许的,因为标准是这样说的。
ISO C ++ - 98 (第14.2节)
模板声明只能作为命名空间或类范围声明出现。
这有意义吗?
答案 2 :(得分:2)
为什么会这么简短,这是因为那些编写c / c ++编译器和标准的人都希望如此。函数内部的模板必须被认为太混乱和/或难以理解或解析,因此他们禁止它。
答案 3 :(得分:2)
“因为标准如此”的答案当然是正确的,但让我们考虑通用lambda。
在C ++ 14和C ++ 17中,通用lambda是编写我所知道的编写类似模板的代码的唯一方法:
auto lambda = [](auto x) { };
lambda.operator()<int>(0);
从技术上讲,您可以随便编写任何类型的模板代码。尽管您将不得不努力解决该方法的各种限制。
这在C ++ 20中会更简单。使用通用lambda中的模板参数列表,您将可以编写如下代码:
auto size = []<class T>() { return sizeof(T); };
static_assert(4 == size.operator()<int>());
GCC已支持此语法。
答案 4 :(得分:1)
唯一有用的时间是,如果您使用一个函数创建了具有不同类型的模板的多个实例。无论如何,将您的私人课程移出您的职能。如果这开始使你的课变得混乱,那么它们太大了,需要重构。
答案 5 :(得分:1)
我的猜测是难以实现,这就是为什么不允许它(在标准C ++ 03中)。另一方面,在函数之外编写类模板是可接受的解决方案。
答案 6 :(得分:0)
究竟会有什么用?那么你可以声明只能在函数中使用的模板变量吗?这真的很有用吗?