56

Given the following code:

void f() { class A { template <typename T> void g() {} }; } 

g++ 4.4 (and also g++-4.6 -std=gnu++0x) complains: "invalid declaration of member template in local class".

Apparently local classes are not allowed to have template members. What is the purpose of this limitation? Will it be removed in C++0x?

Note: If I make the local class itself a template, rather than giving it a template member:

void f() { template <typename T> class A { void g() {} }; } 

I get "error: a template declaration cannot appear at block scope".

4
  • 1
    I came across this old question while struggling with g++-4.6. It still complains, so I edited the question a little. Hopefully we'll get more answers! Commented Jan 11, 2012 at 18:22
  • @AaronMcDaid: Unfortunately, there isn't much more to say at this point. As litb pointed out in his comment to Crazy Eddie's answer, C++11 did not add support for local classes which are templates or have template members (it added support for using local classes as template parameters to another (nonlocal) class, but that's a different feature). So, g++ is not expected to support this in the near future, except perhaps as a compiler extension. I think it's a shame because it would've been a useful feature, but hey, there's always C++24... Commented Jan 11, 2012 at 19:16
  • c++14 allows generic lambdas to be defined locally with variadic arguments. These are very close to being templates and therefore might be a suitable workaround Commented Jul 12, 2015 at 20:14
  • @HighCommander4 It's 2022, yet not supported. Commented Nov 28, 2022 at 4:07

2 Answers 2

11

The purpose of this limitation? Just a guess, but:

  • you may use the template class/template member function only within the enclosing function. Therefore you already know all used types within the function and hence can directly specify the used types (for several types, of course, the template variant would have saved some typing).
  • although it might not seem so, it is work for all compiler creators and space for bugs and so it must be worth the effort.

Fun Fact: Try to use a local class within a function as a return type for a (c++0x)-lambda function declared in the function: MSVC 2010: internal compiler error ^^.

Sign up to request clarification or add additional context in comments.

4 Comments

You might know the types used, but it still prevents you from using SFINAE tricks without exposing the helper structs.
Actually when the local class is a visitor used with boost::apply_visitor on a boost::variant you don't know the type.
Nor do you know the types involved if the function is in itself a template. This limitation is most likely to make it easier on compiler writers, though I can't see why. Should be able to reuse the code that is for non-local templates.
This doesn't make sense since you might which functions are required for you, but you have still to write them manually.
0

The purpose of both limitations (neither classes nor class member functions defined inside of a function may be templates) is to ease compiler implementation and avoid worries about a number of edge cases related to name resolution and code generation. For example, code generation for template functions and methods is already deferred, and the code generation for nested templates defined inside them would need to be deferred further.

There are a few workarounds available:

  • For standalone functions, move the required template class (and/or required class with template methods) into an anonymous namespace just before that function's definition. If the template class references other types or classes defined in that function, move them to the anonymous namespace, too.

  • For class methods, the trick with the anonymous namespace might not work, especially, if the template class declared locally inside the method needs access to private class members. If possible, declare that local class as another private class member instead.

  • Finally, since C++14, lambdas can have auto parameters and auto return types. In many situations, you may be able to move the required template functionality from a local class to a lambda, especially, if it is only required for a method of a local class.

1 Comment

FWIW, lambda's with auto parameters as a class defined in a local scope with a template operator() method. That right there likely adds back in a large chunk of the corner case that preventing general templates avoids. :-(

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.