Why can't transform(s.begin(),s.end(),s.begin(),tolower) be complied successfully?
Try using ::tolower
. This fixed the problem for me.
What's going on at tolower?
You can see this answered in my answer, that's a function pointer. You can read more about them here: http://en.cppreference.com/w/cpp/language/pointer#Pointers_to_functions
Fundamentally this is a pointer to a function that takes in an int
argument and returns an int
.
The reason the transform
works when using myToLower
and not with an uncast tolower
, is that in code is that the tolower
function is overloaded in the std
namespace by both the locale library's tolower
and the ctype library's tolower
. When only the function name is used as an uncast pointer no overload resolution is performed, and you'll get an error. When you cast the function pointer you're telling the compiler which overload you want.
Disable unwanted overload for tolower
You can't disable the other overload, but there are lots of ways to ensure the correct one is chosen:
int (*lower)(int) = std::tolower;
std::transform(chars.begin(), chars.end(), chars.begin(), lower);
or
std::transform(chars.begin(), chars.end(), chars.begin(), static_cast<int(*)(int)>(std::tolower));
or
std::transform(chars.begin(), chars.end(), chars.begin(), [](int c) { return std::tolower(c); });
or
struct ToLower {
int operator()(int c) const { return std::tolower(c); }
};
std::transform(chars.begin(), chars.end(), chars.begin(), ToLower{});
The first two forms tell the compiler how to choose the right overload from the overload set, because only one of the overloads can be converted to a function pointer of that type.
The second two forms create a wrapper that invokes tolower
so that normal overload resolution finds the right one, and you don't need to take the address of tolower
.
Which tolower in C++?
It should be noted that the language designers were aware of cctype
's tolower
when locale
's tolower
was created. It improved in 2 primary ways:
- As is mentioned in progressive_overload's answer the
locale
version allowed the use of thefacet ctype
, even a user modified one, without requiring the shuffling in of a newLC_CTYPE
in viasetlocale
and the restoration of the previousLC_CTYPE
- From section 7.1.6.2[dcl.type.simple]3:
It is implementation-defined whether objects of
char
type are represented as signed or unsigned quantities. Thesigned
specifier forceschar
objects to be signed
Which creates an the potential for undefined behavior with the cctype
version of tolower
's if it's argument:
Is not representable as
unsigned char
and does not equalEOF
So there is an additional input and output static_cast
required by the cctype
version of tolower
yielding:
transform(cbegin(foo), cend(foo), begin(foo), [](const unsigned char i){ return tolower(i); });
Since the locale
version operates directly on char
s there is no need for a type conversion.
So if you don't need to perform the conversion in a different facet ctype
it simply becomes a style question of whether you prefer the transform
with a lambda required by the cctype
version, or whether you prefer the locale
version's:
use_facet<ctype<char>>(cout.getloc()).tolower(data(foo), next(data(foo), size(foo)));
Why is std::find( s.begin(), s.end(), val ) 1000x slower than s.find(val) for a setint s?
std::find
is a generic algorithm that given a pair of iterators can find a value. And if all it has been given is a pair of iterators the best way to find a value is just to linearly search for it which is O(n).
set::find
is a member function of std::set
and so it knows the data structure its searching over and so can optimise the search. And sorted, balanced trees have excellent searching behavoir of O(log(n))
Web Config Transform not working
The Web.config transforms are only applied as part of a publish operation.
If you wish this to be done as part of an app.config
build operation, then you can use the SlowCheetah - XML Transforms Visual Studio plugin:
http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5
How to convert an instance of std::string to lower case
Adapted from Not So Frequently Asked Questions:
#include <algorithm>
#include <cctype>
#include <string>
std::string data = "Abc";
std::transform(data.begin(), data.end(), data.begin(),
[](unsigned char c){ return std::tolower(c); });
You're really not going to get away without iterating through each character. There's no way to know whether the character is lowercase or uppercase otherwise.
If you really hate tolower()
, here's a specialized ASCII-only alternative that I don't recommend you use:
char asciitolower(char in) {
if (in <= 'Z' && in >= 'A')
return in - ('Z' - 'z');
return in;
}
std::transform(data.begin(), data.end(), data.begin(), asciitolower);
Be aware that tolower()
can only do a per-single-byte-character substitution, which is ill-fitting for many scripts, especially if using a multi-byte-encoding like UTF-8.
Related Topics
Difference Between Returning Reference VS Returning Value C++
How to Set the Padding of Qtableview Cells Through CSS
Move or Named Return Value Optimization (Nrvo)
Is Destructor Called If Sigint or Sigstp Issued
So Can Unique_Ptr Be Used Safely in Stl Collections
Why Aren't Static Const Floats Allowed
Disambiguate Overloaded Member Function Pointer Being Passed as Template Parameter
Why Do Un-Named C++ Objects Destruct Before the Scope Block Ends
Clock Function in C++ with Threads
Calling R's Optim Function from Within C++ Using Rcpp
Osx - Replace Gcc Version 4.2.1 with 4.9 Installed via Homebrew
Can Openssl on Windows Use the System Certificate Store
How to Initialize 3D Array in C++