10

I know the answer to the frequently-asked How do I specify a pointer to an overloaded function?: Either with assignment or with a cast, and every other C++ tutorial uppercases a string like this (give or take static_cast):

transform(in.begin(), in.end(), back_inserter(out), (int(*)(int)) std::toupper);

Or like this:

int (*fp)(int) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp);

Which neatly selects the <cctype> overload of std::toupper.

But this begs the question: How can I select the <locale> overload in a similar manner?

char (*fp2)(char, const std::locale&) = std::toupper;
transform(in.begin(), in.end(), back_inserter(out), fp2);
// error: too few arguments to function

Or, more practically, consider someone trying to use the C++11 std::stoi in an algorithm to convert a vector of strings to a vector of integers: stoi has two overloads (string/wstring), each taking two additional default arguments.

Assuming I don't want to explicitly bind all those defaults, I believe it is impossible to do this without wrapping such call in an auxiliary function or lambda. Is there a boost wrapper or TMP magic to do it for me in completely generic manner? Can a wrapper like call_as<char(char)>(fp2) or, more likely, call_as<int(const std::string&)>(std::stoi) even be written?

4
  • 3
    Can you just use a lambda in your transform command? Easiest and cleanest. Commented Jul 6, 2011 at 22:19
  • I wrote and deleted a comment about bind already being the wrapper you were looking for. Then it occurred to me that you'd have to provide the default values to bind, thus re-defining them. Commented Jul 6, 2011 at 22:20
  • It's better to get the algorithm right before thinking about how to obfuscate the code via template stuff. So, start with algorithm. std::toupper call yields Undefined Behavior if there is a negative argument except EOF value. Commented Jul 7, 2011 at 8:58
  • 1
    You can do auto *x = std::toupper<char>;. That looks considerably shorter. Commented Jul 7, 2011 at 9:05

2 Answers 2

5

It's funny, I was doing something similar. The best way I found to do it was using lambdas as follows, because otherwise, you have to use a typedef to get the right overload and a std::bind to get rid of the locale, or not use the locale. However, this works much more cleanly:

static const std::locale loc;
transform(in.begin(), in.end(), back_inserter(out), [&loc](char c) {
  return std::toupper(c, loc);
});

I use the static to save the effort of reallocating each time.

Or you could get a typedef and do:

 std::bind((LocaleCompare)std::toupper, std::placeholders::_1, loc); // UGLY!
Sign up to request clarification or add additional context in comments.

Comments

0

You could should create a typedef of that functon pointer type, and then cast the function.

typedef char (*LocaleToUpper)(char, const std::locale&) ;
char (*fp2)(char, const std::locale&) = (LocaleToUpper)toupper;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.