Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ closures and templates

Tags:

c++

closures

We all know you can simulate closures in C++98 by defining local structs/classes inside a function. But is there some reason that locally defined structs can't be used to instantiate templates outside of the local scope?

For example, it would be really useful to be able to do things like this:

void work(std::vector<Foo>& foo_array)
{
    struct compareFoo
    {
       bool operator()(const Foo& f1, const Foo& f2) const
       {
         return f1.bar < f2.bar;
       }
    };

    std::sort(foo_array.begin(), foo_array.end(), compareFoo());
}

This would be especially useful if you know you're not going to need to use compareFoo anywhere else in your code. But, alas, this doesn't compile. Is there some reason that the compiler can't instantiate the std::sort template function using a locally defined struct?

like image 881
Charles Salvia Avatar asked Dec 08 '22 06:12

Charles Salvia


2 Answers

There's no better reason than "it's not allowed by the standard".

I believe C++0x is going to lift this restriction, and allow you to use local classes as template parameters freely. But for now, it's not allowed.

like image 92
jalf Avatar answered Dec 30 '22 09:12

jalf


See GOTW #58 - you can't use locally defined classes as arguments to templated types, e.g. vector wouldn't be allowed.

From the C++ standard (14.3.1/2):

   A local type, a type with no linkage, an unnamed
   type or a type compounded from any of these types
   shall not be used as a template-argument for a
   template type-parameter.  [Example:
    template <class T>
    class X { /* ... */ };
    void f()
    {
      struct S { /* ... */ };
      X<S> x3;  // error: local type used as
                //  template-argument
      X<S*> x4; // error: pointer to local type
                //  used as template-argument
    }
   --end example]

Although I don't read this as meaning template functions like std::sort can't use a local class as an argument, apparently gcc thinks otherwise.

The local classes have no linkage (no global name), which seems like something that helps overburned compiler writers and hurts actual programmers. To actually allow a local class S to be used in vector<S> or some function<..,S>, I guess the generated thing would need a unique global name.

like image 45
Jonathan Graehl Avatar answered Dec 30 '22 08:12

Jonathan Graehl