29

Reading C++ Templates: The Complete Guide and it says

Note that templates cannot be declared in a function

It does not give explanation and/or cross reference to any other chapter in the book or external resource.

Could someone help in explaining this. Probably it is explained later in the book but not there yet. If explained earlier, I must have missed it.

Example:

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

I do not understand the error message from gcc either. The error message says:

expected primary-expression before "template"
dubnde
  • 4,359
  • 9
  • 43
  • 63
  • You can't declare new classes either, that's just the way it is, i guess. – Benoît Aug 10 '10 at 13:01
  • 5
    There are several answers that basically say "you can't because you can't". Does anyone know whether there is a good reason to prevent doing this? – Mike Seymour Aug 10 '10 at 13:28
  • 1
    Template arguments must have external linkage. As to why this is a necessity there are some hints provided by Greg Comeau in this c.l.c++.moderated discussion @ http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/f822a008746d1e68/2e9e48a43743e9e1?lnk=gst&q=why+local+templates#2e9e48a43743e9e1 – Abhay Aug 10 '10 at 13:34
  • 1
    @Abhay: that's why classes at function scope can't be template arguments, not why template declarations can't be at function scope. – Mike Seymour Aug 10 '10 at 14:10
  • 2
    @Mike Seymour: If you know the exact reason why don't you just enlighten us :) – Prasoon Saurav Aug 10 '10 at 14:17
  • @Prasoon: I don't know, and I'd like to - that's why I asked. – Mike Seymour Aug 10 '10 at 14:25
  • ok. Found something in ISO/IEC 14882:2003(E). section 14 #4 "A template name has linkage (3.5). A non-member function template can have internal linkage; any other template name shall have external linkage" This ties with Prasoon Saurav answer. – dubnde Aug 10 '10 at 14:31
  • I think the accurate answer to this question can only be provided by Standard guy(s). Anyone out there? – Prasoon Saurav Aug 10 '10 at 14:31
  • @MeThinks: that's a step closer to a reason; now the question is, why must all templates have linkage? – Mike Seymour Aug 10 '10 at 14:47
  • @Mike: I think it has more to do with how the template-support is implemenented by the compilers. As of C++03, it was thought of as too difficult to manage templates with no linkage though this restriction is removed in C++0X. See a snip from Sun's compiler notes :- 7.3.1 Static Instances @ http://docs.sun.com/source/819-3690/Compiling_Templates.html – Abhay Aug 10 '10 at 15:05
  • @Abhay: the C++0x draft still only allows template declarations at namespace or class scope (although it does remove the restriction on template arguments). – Mike Seymour Aug 10 '10 at 15:25
  • 1
    why would you even contemplate doing such a thing? – Tony The Lion May 17 '11 at 14:34
  • 6
    @Tony: The template could be some function object that's only to be used inside this one function. I'd wish I could make those local. – sbi May 17 '11 at 14:39
  • @sbi: in the current standard, you would not be allowed to use that template anywhere, as you cannot pass classes defined inside a function to other templates, so the actual use case for that template would be highly limited. You could still create an instance of that template and use it... – David Rodríguez - dribeas May 17 '11 at 14:50
  • @David: In C++03 you cannot instantiate templates with local types. However, you could use this type with non-templates. (For example, it could derive from a polymorphic base class, and you could use instances to call functions taking references/pointers to that base class.) – sbi May 17 '11 at 15:13
  • @sbi: you are right... I am growing more and more used to static polymorphism and a little less to dynamic polymorphism. – David Rodríguez - dribeas May 17 '11 at 15:31
  • I think local template aliases could be used to reduce boilerplate in some function templates, it would be really great if this restriction would be lifted at least for aliases. – Predelnik Dec 11 '15 at 13:13

5 Answers5

56

The problem is probably linked to the historical way templates were implemented: early implementation techniques (and some still used today) require all symbols in a template to have external linkage. (Instantiation is done by generating the equivalent code in a separate file.) And names defined inside a function never have linkage, and cannot be referred to outside of the scope in which they were defined.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
8

The answer "because standard says so", is of course correct, but let's consider generic lambdas.

In C++14 and C++17 generic lambdas are the only way of writing template-like code that I know of:

    auto lambda = [](auto x) { };
    lambda.operator()<int>(0);

Technically, you can write any kind of template code just with that. Though you'll have to work hard to work around various limitations of this approach.

That will be simpler in C++20 though. With template parameter list in generic lambdas you will be able to write code like this:

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

GCC already supports this syntax.

D. Dmitriy
  • 485
  • 4
  • 9
  • Interesting. Can you partial specialize generic lambdas? – ceztko Jul 05 '20 at 10:58
  • @ceztko you can't partially specialize template functions or methods (in case of generic lambda we have template method `operator()`). You can, however fully specialize lambda's `operator()` (here's an example https://godbolt.org/z/dspRsA), but you'll probably find `if constexpr` and `std::is_same_v` more useful. – D. Dmitriy Jul 07 '20 at 00:44
1

The short answer to why this is, is because that how the guys who wrote the c/c++ compilers and standards wanted it to be. Templates inside functions must have been deemed too chaotic and/or difficult to understand or parse, so they forbade it.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
C.J.
  • 15,637
  • 9
  • 61
  • 77
0

My guess is that it is hard to implement, that's why it is not allowed (in Standard C++03). Writing class templates outside of functions is an acceptable solution from the other hand.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • 1
    That's already implemented since C++14 in generic lambdas: object `[](auto x) {}` has template `operator()`, it just doesn't have it template parameters named. – D. Dmitriy Jan 11 '19 at 15:10
-2

The only time this would be useful would be if you created multiple instances of the template with different types withing the one function. Move your private classes out of your functions anyway. If that starts to clutter up your classes then they are too big and need to be refactored.

Cirdec
  • 24,019
  • 2
  • 50
  • 100
  • 2
    Nevertheless I agree it's an odd inconsistency in the language. Like everyone else says, just chalk it down to: "because that's the way it is." – Cirdec Aug 11 '10 at 02:31