From: Paul Bibbings on 30 Sep 2009 09:26 Hello Mau. I have to say at the outset that I am not very familiar with the Boost Test Library. What I can also say, however, is that, having copied and pasted your code as given, and merely replaced the following: mg wrote: > > BOOST_AUTO_TEST_SUITE(algorithm_util_suite) > > BOOST_AUTO_TEST_CASE(erase_if_map) > { > Map map; > map[0] = "a"; > map[1] = "1"; > map[2] = "c"; > > cpplib::erase_if (map, IsDigit()); > ... with the equivalent: int main() { Map map; map[0] = "a"; map[1] = "1"; map[2] = "c"; cpplib::erase_if (map, IsDigit()); return 0; } I get no compilation errors using gcc 4.4.1 (self-built using cygwin and running in that environment). If we have a look at the choices that your compiler 'thinks' it has (from the error messages it produces) I think we might get some clues as to what the problem might be. I am going to suggest that your compiler is interpreting it's possibilities incorrectly. It gives the following as candidates, leading to the reported ambiguity: Container<T, Alloc>& cpplib::erase_if(Container<T, Alloc>&, Predicate) // #1 [with T = int, Alloc = std::string, Container = std::map, Predicate = IsDigit ] void cpplib::erase_if(MapClass<Key, T, Compare, Alloc>&, Predicate) // #2 [with Key = int, T = std::string, Compare = std::less<int>, Alloc = std::allocator<std::pair<const int, std::string> >, MapClass = std::map, Predicate = IsDigit ] Now, if my understanding is correct, the first of these two 'candidates' (#1) should not be considered. The first function parameter to the first candidate is: Container<T, Alloc>& std::map should not match this. std::map is declared as: template < class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map; You'll see that it's last two template parameters have defaults. For your instantiation of std::map, this equates to: std::map< int, std::string, std::less<int>, std::allocator<std::pair<const int, std::string> > > where the defaults can be 'accepted' in certain circumstances, for example, allowing the declaration of an instance as: std::map<int, std::string> a_map; However, your compiler is similarly making use of the defaults to attempt a match to Container<T, Alloc>&, and it is this that I believe is wrong. std::map takes *four* template arguments, and the first attempted instantiation above should not, therefore, be considered a candidate since the defaults should not be considered for the purposes of matching. I am, of course, open to correction on this. (In truth, I have encountered the same myself with older compiler versions (gcc 4.3.2, IIRC).) However, I am wanting to maintain that your code is correct, but your compiler is failing you. Regards Paul Bibbings -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Paul Bibbings on 30 Sep 2009 17:10 mg wrote: > template< > typename Key, > typename T, > typename Compare, > typename Alloc, > template<typename, typename, typename, typename> class MapClass, > typename Predicate > > > void erase_if(MapClass<Key, T, Compare, Alloc>& map, Predicate p); <snip></snip> > If I try to fully qualify the call this way: > cpplib::erase_if<Map::key_type, Map::value_type, Map::key_compare, > Map::allocator_type, Map, IsDigit> (map, IsDigit()); > > It still does not find it: > C:\projects\cpplib\test\algorithm_util_test.cpp|30|error: no matching > function for call to `erase_if(Map&, IsDigit)'| > > Any suggestions ? In the absence of your compiler providing effective overload resolution, as I suggest in my previous post to this thread, you /can/ "force it" by supplying explicit template arguments, as you attempt here. However, you have missed it by just a shade. Try: cpplib::erase_if< Map::key_type, Map::mapped_type, // #1 Map::key_compare, Map::allocator_type, std::map, // #2 IsDigit > (map, IsDigit()); Notes: #1: value_type for std::map is std::pair<const Key, T>, which is not what you want here; #2: here you are matching a template template parameter. For this you supply the name without the template arguments. Your Map is: std::map<int, std::string> so you want just std::map. Regards Paul Bibbings -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: mg on 1 Oct 2009 07:40
Paul wrote: > > In the absence of your compiler providing effective overload resolution, as I > suggest in my previous post to this thread, you /can/ "force it" by supplying > explicit template arguments, as you attempt here. However, you have missed it by > just a shade. Try: > > cpplib::erase_if< > Map::key_type, > Map::mapped_type, // #1 > Map::key_compare, > Map::allocator_type, > std::map, // #2 > IsDigit > > (map, IsDigit()); > Hi Paul, That worked fine. I will upgrade to gcc 4.4.1 and try again without qualifying all the parameters. Thank you so much for taking the time to answer these questions. Your explanations and examples were crystal clear and your help was invaluable ! Cheers, Mau. -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |