C++11 trying to extract a substring using regex - c++

This is my application:
// regex_example.cpp:
// How to compile:
// $ g++ -std=c++11 regex_example.cpp -o regex_example
#include <iostream>
#include <string>
#include <regex>
int main()
{
std::string input = "Pizza Carrot Lasagna 15000 ";
std::smatch match;
std::regex test_reg("[^0-9]*([0-9]+).*");
if (std::regex_search(input.begin(), input.end(), match, test_reg))
{
std::cout << "This is the string found: " << match[1] << std::endl;
}
return 0;
}
When I compile it, this is what the compiler shows me:
regex_example.cpp: In function ‘int main()’: regex_example.cpp:24:68:
error: no matching function for call to
‘regex_search(std::__cxx11::basic_string::iterator,
std::__cxx11::basic_string::iterator, std::__cxx11::smatch&,
std::__cxx11::regex&)’ if (std::regex_search(input.begin(),
input.end(), match, test_reg))
Basically, I'm trying to do the following:
1 - Have this compile. I don't understand why I'm getting the syntax error.
2 - From the input string, I'm trying to extract the number 15000. I'm assuming that when I get this compiling, I will get a string of 15000.

Using
std::regex_search(input.begin(), input.end(), match, test_reg)
Calls the overload
template< class BidirIt, class Alloc, class CharT, class Traits >
bool regex_search( BidirIt first, BidirIt last,
std::match_results<BidirIt,Alloc>& m,
const std::basic_regex<CharT,Traits>& e,
std::regex_constants::match_flag_type flags =
std::regex_constants::match_default );
and it requires that the match_result to be a std::match_results<BidirIt,Alloc>. In this case that is a std::string::iterator but match, which is a std::smatch, uses a std::string::const_iterator. Since those do not match, the compiler is unable to determine what BidirIt should deduce to.
There are many ways you can work around this but the simplest solution is to just use the std::string overload like:
std::regex_search(input, match, test_reg)
(Live Example)

Related

Ambiguous overloading due to Boost headers when compiling C++98 code with C++11 option

Abstract :
My C++98 code uses some boost libraries and some own functions (existing in C++11) defined in a own namspace. It compiles very well with gcc 4.8.x. When I try to compile it with option -std=c++11, I get a call to overloaded xxx is ambiguous error on my own function in my own namespace. This function exists in C++11 in namespace std. It looks like boost calls using namespace std; in a header...
Details :
Consider the following simple code :
#include <vector>
#include <iostream>
#include <boost/math/special_functions/erf.hpp>
namespace caduchon
{
template <typename Iterator>
bool is_sorted(Iterator begin, Iterator end)
{
if(begin == end) return true;
for(Iterator it = begin, prev = it++; it != end; prev = it++)
if(*it < *prev) return false;
return true;
}
}
using namespace caduchon;
int main()
{
std::vector<double> x(3);
x[0] = 10.0; x[1] = 13.9; x[2] = 21.3;
std::cout << "Is x sorted ? " << is_sorted(x.begin(), x.end()) << std::endl;
// Imagine here a call to boost::math::erf(double)
return 0;
}
It compiles very well with gcc 4.8.5 with the following command : g++ test.cpp -o test.exe -I /softs/boost/1.63.0/64/gcc/4.8.5/include
I have an error if I add the option -std=c++11 in the compilation command :
g++ test.cpp -o test.exe -I /softs/boost/1.63.0/64/gcc/4.8.5/include -std=c++11
test.cpp: In function ‘int main()’:
test.cpp:28:61: error: call of overloaded ‘is_sorted(std::vector<double>::iterator, std::vector<double>::iterator)’ is ambiguous
std::cout << "is sorted ? " << is_sorted(x.begin(), x.end()) << std::endl;
^
test.cpp:28:61: note: candidates are:
test.cpp:9:7: note: bool caduchon::is_sorted(Iterator, Iterator) [with Iterator = __gnu_cxx::__normal_iterator<double*, std::vector<double> >]
bool is_sorted(Iterator begin, Iterator end)
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from /softs/boost/1.63.0/64/gcc/4.8.5/include/boost/math/tools/config.hpp:18,
from /softs/boost/1.63.0/64/gcc/4.8.5/include/boost/math/tools/promotion.hpp:26,
from /softs/boost/1.63.0/64/gcc/4.8.5/include/boost/math/special_functions/detail/round_fwd.hpp:12,
from /softs/boost/1.63.0/64/gcc/4.8.5/include/boost/math/special_functions/math_fwd.hpp:26,
from /softs/boost/1.63.0/64/gcc/4.8.5/include/boost/math/special_functions/erf.hpp:13,
from test.cpp:3:
/usr/include/c++/4.8/bits/stl_algo.h:3952:5: note: bool std::is_sorted(_FIter, _FIter) [with _FIter = __gnu_cxx::__normal_iterator<double*, std::vector<double> >]
is_sorted(_ForwardIterator __first, _ForwardIterator __last)
I don't have the error if I remove the inclusion for boost::math::erf function.
I don't have the error if I replace is_sorted by caduchon::is_sorted (but I don't want to impact all my code).
It realy looks like a header of boost calls using namespace std; when option -std=c++11 is defined.
Why ? In my opinion, it's a very bad practice to call using namespace ...; in a header... Is it a bug ?
Is there a simple solution not intrusive for my code ?
Note : I have to compile with option -std=c++11 to be able to use Boost.Process (from Boost 1.64) in a specific module of my code, for a specific platform, with specific compilation flags. The rest of the code must compile under old gcc (4.4.x).
Argument-dependent_name_lookup (ADL) in action:
x.begin() return type is std::vector<double>::iterator.
if it belongs to std namespace, then
is_sorted(x.begin(), x.end())
is look up in namespace std too.
Boost might add some include (<algorithm>) conditionally to support c++11 features in its header.
That happens without any using namespace std;

Wrong attribute of sequence parser

I tried the following example from the spirit x3 docs
#include <string>
#include <iostream>
#include "boost/spirit/home/x3.hpp"
namespace x3 = boost::spirit::x3;
int main()
{
std::pair<double, double> p;
std::string input("1.0 2.0");
std::string::iterator input_pos = input.begin();
x3::phrase_parse(input_pos, input.end(),
x3::double_ >> x3::double_,
x3::space, p);
}
The error i get is
[...]/boost/boost-1.61.0/include/boost/spirit/home/x3/support/traits/move_to.hpp:62:18: error: no match for ‘operator=’ (operand types are ‘std::pair<double, double>’ and ‘std::remove_reference<double&>::type {aka double}’)
dest = std::move(src);
If i change p to be of type double it compiles and matches 2.0. This is obviously not my intention. I tried this with multiple version of gcc (4.9, 6.2, trunk) and boost version 1.61.0. I feel like this should be a configuration problem unless someone spots an error in the code.
Did someone experienced something similar and know where the problem lies?

std::thread calling template function out of template function

I am trying to create threads out of a template function giving the thread another template function.
I have appended an expample of the situation that gives the same errors. Giving the thread a function that is not templated (ie here one with int and one with float) does not result in an error.
However since I plan to use this function with many different types I don't want to specify the template types. Also I have tried several specifyings of the template type (eg std::thread<T> or std::thread(function<T>) without any success.
Question: How can I call a template function with a std:thread out of a template function?
The following is a minimum compiling example of the situation, in reality the templates are own classes:
#include <thread>
#include <string>
#include <iostream>
template<class T>
void print(T* value, std::string text)
{
std::cout << "value: " << *value << std::endl;
std::cout << text << std::endl;
}
template<class T>
void threadPool(T* value)
{
std::string text = "this is a text with " + std::to_string(*value);
std::thread(&print, value, text);
}
int main(void)
{
unsigned int a = 1;
float b = 2.5;
threadPool<unsigned int>(&a);
threadPool<float>(&b);
}
compiling this example with g++ or icc with:
icc -Wall -g3 -std=c++11 -O0 -pthread
gives the folowing error messages (icc):
test.cpp(17): error: no instance of constructor "std::thread::thread" matches the argument list
argument types are: (<unknown-type>, unsigned int *, std::string)
std::thread(&print, value, text);
^
detected during instantiation of "void threadPool(T *) [with T=unsigned int]" at line 24
test.cpp(17): error: no instance of constructor "std::thread::thread" matches the argument list
argument types are: (<unknown-type>, float *, std::string)
std::thread(&print, value, text);
^
detected during instantiation of "void threadPool(T *) [with T=float]" at line 25
compilation aborted for test.cpp (code 2)
Thank you very much in advance
That's because just print is not a complete type.
I haven't tried it, but doing e.g. &print<T> should work.
Unrelated, but there's no need to pass pointers to your threadPool function. Passing a (possible constant) reference would probably be better.
Use this:
template<class T>
void threadPool(T* value)
{
std::string text = "this is a text with " + std::to_string(*value);
std::thread(&print<T>, value, text);
}
Try
std::thread([value,text]() { print(value, text); });

std::remove_if and std::isspace - compile-time error

I have the following code:
#include <algorithm>
#include <cctype>
#include <string>
int main()
{
std::string str;
str.erase(std::remove_if(str.begin(), str.end(), std::isspace), str.end());
}
MSVC-11.0 compiles this code without any error, but gcc 4.7.2 gives me the following errors:
main.cpp: In function ‘int main()’:
main.cpp:8:66: error: no matching function for call to ‘remove_if(std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unresolved overloaded function type>)’
main.cpp:8:66: note: candidate is:
In file included from /usr/include/c++/4.7/algorithm:63:0,
from main.cpp:1:
/usr/include/c++/4.7/bits/stl_algo.h:1160:5: note: template<class _FIter, class _Predicate> _FIter std::remove_if(_FIter, _FIter, _Predicate)
/usr/include/c++/4.7/bits/stl_algo.h:1160:5: note: template argument deduction/substitution failed:
main.cpp:8:66: note: couldn't deduce template parameter ‘_Predicate’
I found this question about it, but according to the cppreference, there isn't any version of this function that takes two arguments. I found this question too, but according to the cppreference (yep, again) I see that there's only one std::isspace function overload.
Who's right? What am I doing wrong? How can I fix it?
There is another overload of std::isspace, so you need to specify which one to use. An easy way is to use a lambda (or write your own one-line function if you don't have C++11 support):
std::remove_if(str.begin(), str.end(),
[](char c){
return std::isspace(static_cast<unsigned char>(c));
});
std::isspace is an overloaded function, although the two overloads reside in different headers. Also note that your code may introduce undefined behaviour because only values in the range 0..UCHAR_MAX can be passed to std::isspace, whereas a char is possibly signed.
Here is a solution:
std::string str;
auto f = [](unsigned char const c) { return std::isspace(c); };
str.erase(std::remove_if(str.begin(), str.end(), f), str.end());
The following solution should get you around the compile-time error:
str.erase(std::remove_if(str.begin(), str.end(), (int(*) (int)) std::isspace), str.end());
After C++ 11, you can use lamda function (easier to understand), see below:
string s = " 3/ 2";
auto isSpace = [](const unsigned char c)
{
return std::isspace(c);
};
s.erase(remove_if(s.begin(), s.end(), isSpace), s.end());
Output:
3/2

Removing a character from a string

i have a string. I want to delete the last character of the string if it is a space.
i tried the following code,
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
but my g++ compiler gives me an error saying:
error: no matching function for call to ‘remove_if(__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>)’
please help.
The first problem is that isspace has multiple overloads in the C++ Standard Library. The initial fix is to provide an explicit type for the function so that the compiler knows which function to take the address of:
#include <string>
#include <algorithm>
#include <cctype>
int main()
{
std::string str = "lol hi innit";
str.erase(std::remove_if(str.begin(), str.end(), (int(*)(int))isspace), str.end());
std::cout << str; // will output: "lolhiinnit"
}
It's a big ugly but, hey, this is C++.
Second, your code will remove all spaces in the string, which is not what you seem to want. Consider a simple if statement on the last character of the string:
#include <string>
#include <cassert>
int main()
{
std::string str = "lol hi innit ";
assert(!str.empty());
if (*str.rbegin() == ' ')
str.resize(str.length()-1);
std::cout << "[" << str << "]"; // will output: "[lol hi innit]"
}
Hope this helps.
I think it can't figure out what isspace is (according to the "unresolved overloaded function type" as a third parameter to remove_if in the error message). Try ::isspace, and include ctype.h
I had the exact same problem as you, so I got rid of isspace. I just went with this:
str.erase(std::remove_if(str.begin(),str.end(),' '),str.end());
That worked for me with Visual C++ 2012, using Visual Studio 2012. See if it works for you.
You are missing an std:: for remove_if