tags:

views:

48

answers:

3

I'm trying to compile the following program using Qt Creator 2.0.1:

void f()
{
    string a = "abc";
    transform(a.begin(), a.end(), a.begin(), ptr_fun(tolower));
}

mingw throws the following error:

no matching function for call to ptr_fun( < unresolved overloaded function type > )

That function compiles fine with VC++ 2010 Express. What is wrong with mingw?

Thanks.

+1  A: 

Why don't you just call

transform (a.begin, a.end(), a.begin(), tolower);

?

Armen Tsirunyan
@Armen: for reasons unconnected to the question, is why not ;-)
Steve Jessop
A: 

Nothing is wrong with mingw. There are multiple overloads for tolower, generating the message "unresolved overloaded function.

You need to specify which overload you want to use, eigher via some cast (int)(*)(char)tolower or an intermediate variable.

André Caron
+2  A: 

The problem is the ambiguity introduced by the function template

template <class charT> charT tolower(charT c, const locale& loc);

I guess that mingw has included <locale> indirectly from one of the headers your program includes, whereas VC++ didn't.

You can fix this by disambiguating tolower with a cast:

typedef int (*foo)(int);
ptr_fun((foo)tolower);

Or if you like maintenance programmers to throw shoes at you:

ptr_fun((int (*)(int))tolower);

Note that as Armen says, you don't actually need ptr_fun here. It converts a Unary Function into an Adaptable Unary Function, but transform doesn't need its parameter to be adaptable. The difference is whether the type has nested typedefs for argument_type and result_type. Raw function types don't, ptr_fun returns a functor type that does.

Finally, it's not in general safe to call the C tolower on a char if char is signed on your platform. Your example string is OK, because none of the characters in "abc" is negative, but you should do something like this:

char fixed_tolower(char c) {
    return tolower((unsigned char)c);
}

transform(..., fixed_tolower);

Or for a better chance of inlining:

struct fixed_tolower : unary_function<char, char> {
    char operator()(char c) const {
        return tolower((unsigned char)c);
    }
};

transform(..., fixed_tolower());

I haven't checked whether it actually makes any difference in GCC, either from the POV of inlining or from the POV of whether the mingw implementation of tolower actually barfs on negative numbers.

Steve Jessop