C++ 为什么可以';不能在函数中声明模板吗?

C++ 为什么可以';不能在函数中声明模板吗?,c++,templates,C++,Templates,阅读,它说 请注意,不能声明模板 在函数中 它不解释和/或交叉引用本书中的任何其他章节或外部资源 有人能帮我解释一下吗。这本书后面可能会解释,但现在还没有。如果早点解释的话,我一定错过了 例如: int main() { class DummyClass // This compiles ok { int object; }; template <typename T> // compile error "expected primary-expres

阅读,它说

请注意,不能声明模板 在函数中

它不解释和/或交叉引用本书中的任何其他章节或外部资源

有人能帮我解释一下吗。这本书后面可能会解释,但现在还没有。如果早点解释的话,我一定错过了

例如:

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;
}

这意味着你不能做如下的事情

  void foo()
  {
       template <typename T> //Error
       T something;
  }
void foo()
{
模板//错误
不是什么东西;
}
模板声明仅允许在全局、命名空间或类范围内使用。:)

背后的原因是什么

这是不允许的,因为标准上这么说

ISO C++-98(第14.2节)

模板声明只能作为命名空间或类范围声明出现


这有意义吗?

到底有什么用?那么您可以声明只能在函数中使用的模板变量?这真的有用吗?

关于这一点的简短答案是,编写c/c++编译器和标准的人希望它是这样的。函数中的模板必须被认为过于混乱和/或难以理解或解析,因此他们禁止使用它。

唯一有用的方法是使用一个函数创建多个不同类型的模板实例。无论如何,还是要将私有类移出函数。如果这开始使您的类变得混乱,那么它们太大了,需要重构。

我猜这很难实现,这就是为什么不允许(在标准C++03中)。从另一方面来说,在函数之外编写类模板是一种可以接受的解决方案。

这个问题可能与模板实现的历史方式有关:早期的实现技术(有些至今仍在使用)要求模板中的所有符号都具有外部链接。(实例化是通过在一个单独的文件中生成等效代码来完成的)。函数中定义的名称从来没有链接,也不能被引用到它们定义的范围之外。

< p>答案“因为标准是这样说的”,当然是正确的,但是让我们考虑通用lambdas。< /p> 在C++14和C++17中,泛型lambda是我所知道的编写类似模板的代码的唯一方法:

    auto lambda = [](auto x) { };
    lambda.operator()<int>(0);
autolambda=[](autox){};
lambda.operator()(0);
从技术上讲,您可以用它编写任何类型的模板代码。尽管您必须努力克服此方法的各种限制

不过,在C++20中,这将更简单。使用generic lambdas中的模板参数列表,您将能够编写如下代码:

    auto size = []<class T>() { return sizeof(T); };
    static_assert(4 == size.operator()<int>());
auto size=[](){return sizeof(T);};
静态断言(4==size.operator());


GCC已经支持此语法。

是。谢谢。问题是为什么会这样。背后的原因是什么?
背后的原因是什么?
。我不知道关于在函数中实现模板声明的很多技术细节,但这是标准所不允许的。ISO C++(14.2)说:“代码> A*模板声明*只能作为命名空间或类范围声明< /代码>:+ 1出现。谢谢是的,这很有道理。我看到标准不允许这样做。这将有助于理解原因。我看到关于标准不允许(不允许)的问题得到了一些支持标准的解释。对我这样的学习者很有帮助。这绝不会从这个非常好的答案中拿走任何东西。好吧,我也不赞成从函数中声明结构/函数。我总是发现它把代码弄得一团糟。无论如何,我认为这有助于简化编译器编写人员的工作,而且他们的工作非常艰巨,因为不需要这种“特性”,因为它不会带来太多的结果。“它是不允许的,因为它是不允许的”对于问“为什么?”的问题是无效的回答,也是一个逻辑谬误。是的。我可以用结构和类来实现这一点。我唯一能想到的是函数对象,它与类/结构有关,用于函数中的算法。不需要,但我这样做是为了让类/结构靠近我使用它们的地方。我可能有一些原因,但这更多的是一个学习练习。事实上,它可能没有用处,我想这是一个不同的讨论。它的用处实际上不是另一个讨论,在我看来,它与这个讨论非常相关。如果这真的被允许,你将如何使用它?调用方看不到函数的内部,因此在调用此函数时,如何用适当的类型实例化模板参数?@Preatirian。我听到了。但是,我可能不一定需要传递模板参数。我可以在函数中多次使用模板,使用不同的模板参数。我只是在这里大声思考来学习:)@Praetorian抱歉拼错了name@Praetorian:在C++03中,不能使用本地类型实例化模板。但是,您可以将此模板的实例与非模板一起使用。(例如,它可以派生自多态基类,您可以使用实例调用引用/指针指向该基类的函数。)谢谢。这很容易理解,也很有道理。有任何参考资料吗?@MeThinks:请看我对你的评论的评论。有几个答案基本上是“你不能,因为你不能”。有人知道是否有充分的理由阻止这样做吗?@Abhay:这就是为什么函数作用域中的类不能成为模板参数,不是为什么模板声明不能在函数范围内。@Mike Seymour:如果你知道为什么不告诉我们的确切原因:)你为什么会考虑做这样的事情?@Tony:模板可能是一些函数对象,只能在这个函数范围内使用
    auto size = []<class T>() { return sizeof(T); };
    static_assert(4 == size.operator()<int>());