Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old May 30th, 2006, 7:09 PM   #1
manannan
Newbie
 
Join Date: May 2006
Posts: 2
Rep Power: 0 manannan is on a distinguished road
Using internal classes in STL functions

When using the STL, I'd often want to instantiate an anonymous functor -- something like this:
#include <set>
#include <algorithm>

int main()
{
  std::set<int> s;
  s.insert(1); s.insert(2);

  class
  {
  public:
    bool operator () (int a, int b) { return a < b; }
  } comparer;

  bool test = comparer(1, 2); // Works
  return *( std::max_element(s.begin(), s.end(), comparer) ); // Fails!
}
The problem is, under gcc, this fails with the error
test.cpp:17: error: no matching function for call to ‘max_element(std::_Rb_tree_const_iterator<int>, std::_Rb_tree_const_iterator<int>, main()::<anonymous class>&)’
Looking at the <algorithm> header, I say that the error message makes no sense, and the program should compile just fine.
Now it seems that the only way for me to use a functor is to make its class global. But isn't there a way to somehow avoid cluttering the global namespace and keep the code beautiful? Or should I report a bug in the gcc? :-)

Last edited by manannan; May 30th, 2006 at 7:34 PM.
manannan is offline   Reply With Quote
Old May 30th, 2006, 8:01 PM   #2
The Dark
Expert Programmer
 
Join Date: Jun 2005
Posts: 850
Rep Power: 4 The Dark is on a distinguished road
You can't do it in Visual Studio either (I'm not sure why there is this restriction, but there is probably a good reason).
Quote:
illegal use of anonymous local type in template instantiation

You cannot generate a template function (a function from a function template) based on a local type. Types used to instantiate templates must have external linkage.
Even if you give it a name, you get:
Quote:
'name' : illegal use of local type in template instantiation

You cannot generate a template function (a function from a function template) based on a local type. Types used to instantiate templates must have external linkage.
One way to fix this is to use your own namespace. It is a bit uglier as the class has to be outside of your function.
#include <set>
#include <algorithm>

namespace myNamespace
{
  class comparer
  {
  public:
    bool operator () (int a, int b) { return a < b; }
  };
}

int main()
{
  std::set<int> s;
  s.insert(1); s.insert(2);

  myNamespace::comparer comparer;

  bool test = comparer(1, 2); // Works
  return *( std::max_element(s.begin(), s.end(), comparer) ); // Fails!
}
The Dark is offline   Reply With Quote
Old May 30th, 2006, 8:48 PM   #3
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,222
Rep Power: 5 grumpy is on a distinguished road
The reason comes down to how templates are instantiated. In essence, a template can only be instantiated for types that have external linkage (in your context, they cannot be anonymous). If you want to avoid cluttering the global namespace with your algorithms, place them in a namespace of their own.

In this example, as you're using <algorithm> anyway, why not use this?
   return *( std::max_element(s.begin(), s.end(), std::less<int>()) );
grumpy is offline   Reply With Quote
Old May 30th, 2006, 9:24 PM   #4
manannan
Newbie
 
Join Date: May 2006
Posts: 2
Rep Power: 0 manannan is on a distinguished road
Thank you, Dark and Grumpy. When I grow up, I'll weasel my way into the ISO C++ Standards Committee and make them abolish the restriction.
Overloading operator < for my classes seems like a good solution in this case -- though I use functors for more than finding max_element(). Thanks for the idea.
manannan is offline   Reply With Quote
Old May 31st, 2006, 1:25 AM   #5
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,222
Rep Power: 5 grumpy is on a distinguished road
Quote:
Originally Posted by manannan
Thank you, Dark and Grumpy. When I grow up, I'll weasel my way into the ISO C++ Standards Committee and make them abolish the restriction.
I wish you good hunting, but am prepared to bet you won't succeed. The reason for the restriction is to allow C++ implementations flexibility of how they implement template instantiation behind the scenes. Some implementations use template repositories, and the actual process of template instantiation happens at link time rather than at compile time (that means a smarter linker working with a slightly dumber compiler). The benefit of such schemes is reducing code bloat (eg multiple identical instantiations of a template within a single executable) by allowing the linker to instantiate each template specialisation only once. A side-effect of such schemes is that all template type parameters must have external linkage.

Last edited by grumpy; May 31st, 2006 at 1:35 AM.
grumpy is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 4:44 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC