Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does ptr_fun(tolower) doesn't compile in mingw?

Tags:

c++

mingw

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.

like image 430
Donotalo Avatar asked Oct 30 '10 19:10

Donotalo


2 Answers

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.

like image 117
Steve Jessop Avatar answered Oct 11 '22 09:10

Steve Jessop


Why don't you just call

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

?

like image 25
Armen Tsirunyan Avatar answered Oct 11 '22 09:10

Armen Tsirunyan