为什么不能在函数中声明模板?

时间:2010-08-10 12:55:40

标签: c++ templates

阅读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"

7 个答案:

答案 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)

究竟会有什么用?那么你可以声明只能在函数中使用的模板变量吗?这真的很有用吗?