Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

C++ headache

Started by Mayrel 6 replies 2.1k views
Original Post
Mayrel
Mayrel
I wanted to convert a string to uppercase, and I figured I'd do it with transform and toupper:

std::transform(string.begin(), string.end(), string.begin(), toupper);
Then I thought I'd try to use the C++ version of toupper. So far, I've gotten to:

std::transform(string.begin(), string.end(), string.begin(),
               static_cast<char(std::ctype<char>::*)(char)const>
                  (std::use_facet<std::ctype<char> >(std::locale()).toupper));
But the compiler says error C2475: 'std::ctype<char>::toupper' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name. But when I use &, it says it's an illegal operation on bound member function expression. What's going on?
me22
me22
Thanks for quite an instuctive question =)

Just in general, if you have to cast something like that explicitly it's almost surely the wrong approach...

If you say:

std::transform(string.begin(), string.end(), string.begin(), &std::ctype<char>::toupper );

then what it tries to do it:

(&std::ctype<char>::toupper)( *on_iterator );

which is certainly wrong.

You have to use binders to make it into a member function functor, then bind the address of the object to get it down to a normal unary functor. mem_fun and bind1st and bind2nd are your friends ( or boost::bind if you prefer nice(r) syntax :P ).

Here's my little test program:
#include <iostream>#include <string>#include <algorithm>#include <locale>#include <boost/bind.hpp>int main() {	std::string s = "tEstING...\n";	const std::ctype<char> &c = std::use_facet< std::ctype<char> >( std::locale() );	typedef char ( std::ctype<char>::* char_ctype_char_const_ptr)(char)const;	char_ctype_char_const_ptr fp = &std::ctype<char>::toupper;	std::transform( s.begin(), s.end(), s.begin(),/* uncomment your functor and syntax of choice *///		toupper );					std::bind1st( std::mem_fun( fp ), &c ) );//		boost::bind( fp, &c, _1 ) );//		boost::bind( fp, boost::ref(c), _1 ) );	std::cout << s << std::endl;	return 0;}


The uncommented line is the method you were hoping to use, in a standards-compliant way. toupper's there for testing, and the boost methods are nicer ways.

Note that you can't copy std::ctype<char> s ( protected destructor ), so you have to use references or pointers in the binding -- neither of the following work:
std::bind1st( std::mem_fun_ref( fp ), c ) );
boost::bind( fp, c, _1 ) );

* me22 closes _The_C++_Programming_Language_ :)
Fruny
Fruny
There are two overloads of toupper, one in <cctype>, one in <locale>. To select the one you want (likely the one in <cctype>), cast the pointer thusly (int (*)(int)) &toupper.

std::transform(str.begin(), str.end(), str.begin(), (int (*)(int)) &toupper )

Alternatively, grab boost 1.32, and just use the string-specific algorithms they provide.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
ChaosEngine
ChaosEngine
it has to be said, that this is one of the areas the standard library falls down, IMO. They've made what should be a simple, relatively common operation overly complex in order to increase genericity (is that a word?).

What would be wrong with a simple std::string::to_upper() method?

if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight
Fruny
Fruny
Quote:
Original post by ChaosEngine
What would be wrong with a simple std::string::to_upper() method?


What locale should it use?
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Zahlman
Zahlman
Quote:
Original post by Fruny
Quote:
Original post by ChaosEngine
What would be wrong with a simple std::string::to_upper() method?


What locale should it use?


That wouldn't be an issue if everyone would just use Unicode, would it? ::sigh::
qesbit
qesbit
This reminds of the tale of a King, an electrical engineer and a software engineer. The king wanted to design a toaster. To make a long story short, the electrical engineer married his daughter and the king beheaded the software engineer.

ChaosEngine
ChaosEngine
Quote:
Original post by Fruny
Quote:
Original post by ChaosEngine
What would be wrong with a simple std::string::to_upper() method?


What locale should it use?


ok, I'll admit it. I don't really understand locales, (never really had call to use them). But surely a default locale could be speicified in the function arguements?
if you think programming is like sex, you probably haven't done much of either.-------------- - capn_midnight

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.