From: Paul Bibbings on
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
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
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! ]