I'm trying to split a string using the method found in this thread, but I'm trying to adapt it to a wstring. However, I have stumbled upon a weird error. Check the code:
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(void)
{
wstring str(L"Börk börk");
wistringstream iss(str);
vector<wstring> tokens;
copy(istream_iterator<wstring>(iss), // I GET THE ERROR HERE
istream_iterator<wstring>(),
back_inserter< vector<wstring> >(tokens));
return 0;
}
The exact error message is:
error: no matching function for call to 'std::istream_iterator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, char, std::char_traits<char>, int>::istream_iterator(std::wistringstream&)'
I think it is saying that it can't instantiate the istream_iterator using the passed iss (which is a wistringstream instead of a istringstream). This is on a Mac using XCode and GCC 4.2. And AFAIK there is no wistring_iterator or anything like that.
It works perfectly when I'm using the non-wstring version. As you might see I have changed the declarations to use wstring, wistringstreams and vector<wstring>, just replaced everything to use the wide version.
What could cause this and why won't it accept the wstring-version?
Per the latter part of the error message, you have to override the default params 2 and 3 on istream_iterator() to match widechar usage elsewhere. In Visual C++ this version compiles OK for me:
copy(istream_iterator<wstring, wchar_t, std::char_traits<wchar_t> >(iss), // I DO NOT GET THE ERROR HERE
istream_iterator<wstring, wchar_t, std::char_traits<wchar_t> >(),
back_inserter< vector<wstring> >(tokens));
Related
I tried to use std::isgraph from <cctype> as a predicate in find_if. But compiler errored out saying:
error: no matching function for call to ‘find_if(__gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, __gnu_cxx::__normal_iterator< const char*, std::basic_string< char> >, < unresolved overloaded function type>)’
I have used using namespace std; and from my understanding there will be two isgraph functions visible in the global namespace. So ::isgraph or simply isgraph should be ambiguous and std::isgraph should not be ambiguous. On the contrary, using ::isgraph is OK while std::isgraph is not.
Can someone explain what I missed? A few related questions are What are the function requirements to use as the predicate in the find_if from the <algorithm> library? and C++ using standard algorithms with strings, count_if with isdigit, function cast. But they didn't answer why explicitly specifying std:: still doesn't resolve to the function in the std namespace.
EDIT:
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
using namespace std;
int main()
{
string root_line = "hello";
auto ind = distance(root_line.begin(), find_if(root_line.begin(), root_line.end(), std::isgraph));
cout << ind;
return 0;
}
I compiled the above code with g++ -std=c++11 of version 4.8.4
std::isgraph is overloaded.
To resolve the ambiguity you could cast it to the relevant function pointer type.
But in order to use it correctly the argument should be converted to unsigned char, so better define a wrapper function:
using Byte = unsigned char;
auto is_graphical( char const ch )
-> bool
{ return !!isgraph( Byte( ch ) ); }
Note that this only works with single-byte encodings, and that it depends on the current locale at the C level (see setlocale).
There is a std::isgraph defined in <cctype> and a different std::isgraph defiend in <locale>. Using overloaded functions as functors can be a pain as the compiler has difficulty figuring out which version of the function you want. You can resolve the ambiguity by casting, or using a lambda or named wrapper function as suggested by #Cheersandhth.-Alf
#include <cctype>
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string root_line = "hello";
auto ind = std::distance(root_line.begin(), std::find_if(root_line.begin(), root_line.end(), static_cast<int(*)(int)>(std::isgraph)));
std::cout << ind;
}
Live example: http://ideone.com/heSSEZ
This question already has answers here:
std::transform() and toupper(), no matching function
(3 answers)
Closed 9 years ago.
can anyone tell me what is the mistake in this program
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
string str = "Now";
transform(str.begin(), str.end(), str.begin(), toupper);
cout<<str;
return 0;
}
Error:
"no matching function for call to 'transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'
compilation terminated due to -Wfatal-errors."
There are two functions with name toupper. One from cctype header:
int toupper( int ch );
And second from locale header:
charT toupper( charT ch, const locale& loc );
Compiler can't deduce which function should be used, since you allow namespace std. You should use scope resolution operator(::) to choose function defined in global space:
transform(str.begin(), str.end(), str.begin(), ::toupper);
Or, better: Do not use using namespace std.
Thanks to #Praetorian -
This is probably the cause of the error, but adding :: may not always
work. If you include cctype toupper is not guaranteed to exist in the
global namespace. A cast can provide the necessary disambiguation
static_cast<int(*)(int)>(std::toupper)
So, the call should look like:
std::transform
(
str.begin(), str.end(),
str.begin(),
static_cast<int(*)(int)>(std::toupper)
);
In order to use toupper, you need to include header file:
#include <cctype>
You also need to include header file:
#include <string>
The problem is the std::toupper takes int as parameter, while std::transform will pass char into the function, therefore, it has a problem (by courtesy of #juanchopanza).
You may try to use:
#include <functional>
std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun<int, int>(std::toupper));
See example code from std::transform
Or you can implement your own toupper that takes char as argument.
As the compiler has buried in its error message, the real problem is that toupper is an overloaded function, and the compiler can't figure out which one you want. There's the C toupper(int) function which may or may not be a macro (may not in C++, but does the C library care?), and there's std::toupper(char, locale) from (pulled in by without doubt), which you made available globally with your using namespace std;.
Tony's solution works because he accidentally resolved the overloading issue with his separate function.
So I've seen a lot of similar issues but none of the answers are fixing my issue. Can someone explain why this code:
string LinkedListByName::toLower(string stringToConvert){
return std::transform(stringToConvert.begin(), stringToConvert.end(), stringToConvert.begin(), ::tolower); }
is giving me this error:
conversion from `__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >' to non-scalar type `std::string' requested
In the project I'm going to need to convert a lot of strings to lower and boost is NOT an option. I literally copied and pasted this code from previous projects in which it functioned.
Additionally the header file is including the following:
#include <vector>
using namespace std;
#include <iostream>
using namespace std;
#include <string>
using namespace std;
#include <algorithm>
#include "Node.h"
namespace model {
Your method should return string, but instead you try to return iterator from std::transform. Change it to this:
string LinkedListByName::toLower(string stringToConvert){
std::transform(stringToConvert.begin(), stringToConvert.end(), stringToConvert.begin(), ::tolower);
return stringToConvert;
}
To my surprise the following code compiles:
#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>
int main() {
std::string s="nawaz";
std::string S;
std::transform(s.begin(),s.end(), std::back_inserter(S), ::toupper);
std::cout << S ;
}
I had expected it to fail because of the ::toupper which I believed should be in the std namespace. A quick check of cctype shows that it is but it is imported from the root namesapce (Mystery solved there).
namespace std
{
// Other similar `using` deleted for brevity.
using ::toupper;
}
So first problem solved but if I change the transform() line above too:
std::transform(s.begin(),s.end(), std::back_inserter(S), std::toupper);
I would now expect this to now also compile. But I get a compiler error:
kk.cpp:12: error: no matching function for call to `transform(__gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::cha
r_traits<char>, std::allocator<char> > >, std::back_insert_iterator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, <unresolved overloaded function type>)'
Which with manual editing resolved too:
kk.cpp:12: error: no matching function for call to
`transform(iterator<std::string>,
iterator<std::string>,
std::back_insert_iterator<std::string>,
<unresolved overloaded function type>)'
What am I missing?
It doesn't work because there are overloads of std::toupper. You can fix it by casting to your desired function overload:
std::transform(s.begin(),s.end(), std::back_inserter(S),
(int(&)(int))std::toupper);
You're missing that C++ also adds new toupper functions in <locale> which is probably included implicitly by one of your other headers. Thus in the std:: namespace there are multiple overloads while in the global namespace there is only the old C version of the function.
That said it does still seem like g++ should be able to deduce the correct overload.
Like others said the problem is that std::toupper and friends are overloaded.
One way to fix this is to use a lambda.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main()
{
std::string s{ "This is a test" };
std::string S{};
std::transform(s.begin(), s.end(), std::back_inserter(S), [] (char ch){ return std::toupper(ch); });
std::cout << S;
return 0;
}
I realize this is an old post but as many, including myself, still encounter this issue, I hope my post will be helpful.
I have the following code snippet. I am compiling using the sun studio 12 compiler and have tried boost 1.33 and 1.39
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
using namespace boost;
using namespace std;
int main(int argc, char* argv[])
{
string exbyte = "0x2430";
string exbytes = "0x2430,2430";
typedef vector< string > SplitVec;
SplitVec res1 ;
split(res1 , exbyte, is_any_of(",") );
return 0
}
I get the following compile error:
"/bb/source/boost/boost_1_39_0/boost/algorithm/string/iter_find.hpp", line 175: Error, nomatchoverin: Could not find a match for std::vector::vector(boost::transform_iterator, boost::algorithm::split_iterator, boost::use_default, boost::use_default>, boost::transform_iterator, boost::algorithm::split_iterator, boost::use_default, boost::use_default>) needed in boost::algorithm::iter_split, std::string, boost::algorithm::detail::token_finderF>>(std::vector&, std::string &, boost::algorithm::detail::token_finderF>)
If anybody has thoughts on this that would be awesome. Since I am cotemplateing strtok(only kidding)
Other than the missing semi-colon after return 0, which I assume is an unrelated typo, your code compiles fine for me, using gcc 4.3.2.
According to the documentation for boost::split, you're using the function correctly, so I don't think this is a coding error. Are you sure you have boost installed correctly?
Edit: It may be that Boost doesn't support your particular compiler, so parts of boost may not work for you. See here for a list of supported compilers, along with various issues which affect each compiler.
It sounds like your compiler's STL implementation only provides a vector ctor taking vector::iterator's and not any iterator class. You can verify this by taking a look at the vector header file.
You may able to work around this by using STLPort which apparently can be used with Sun Studio 12.