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?
Related
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)
I have the following lines in my code:
std::vector<std::string> lines;
boost::split(lines, output, boost::is_any_of("\n"));
Where output is a const std::string.
When I compile, I get an error:
error: implicit conversion changes signedness: 'typename range_difference<iterator_range<const char *> >::type' (aka 'long') to 'std::size_t' (aka 'unsigned long') [-Werror,-Wsign-conversion]
std::size_t Size=::boost::distance(Range);
This originates from
boost::split(lines, output, boost::is_any_of("\n"));
^
Seems like an internal typing error in boost?
Anyone encountered this before?
Note: Compiling with gcc version 5.3.1 20160406 (Red Hat 5.3.1-6), most warning flags set and -Werror.
Note2: So as #sehe has shown, this is indeed a boost issue.
So let me change the question - Does anyone know of a workaround for this?
Thanks!
Reproduced issue
https://wandbox.org/permlink/LIf0wzUPQxrz7pik (GCC) and https://wandbox.org/permlink/BofswARbx1BpVE6H (Clang)
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/algorithm/string.hpp>
#include <vector>
#include <string>
int main() {
std::string output;
std::vector<std::string> lines;
boost::split(lines, output, boost::is_any_of("\n"));
}
This should be reported to the maintainers of Boost Algorithm (see the boost mailing list or https://svn.boost.org/trac10/query?status=assigned&status=new&status=reopened&component=string_algo&col=id&col=summary&col=status&col=owner&col=type&col=milestone&order=priority)
Seeing as there's no more activity around this issue I'll close this with saying that yes - this is a boost issue. It's easily reproduced with #sehe 's MCVE.
Apparently compiling boost with strict warnings and Werror flags is impossible.
As per my workaround, I had a fairly simple use-case and I've implemented my own, simple, version of split
inline std::vector<std::string> Split(const std::string &str, char delim)
{
std::vector<std::string> out;
std::stringstream ss(str);
std::string item;
while (std::getline(ss, item, delim)) {
out.push_back(item);
}
return out;
}
I am porting some C++ code from Windows to Linux (and eventually OSX). Tons of C++ issues arise due to Windows non-compliance. I seem to have gotten past that, but am now facing a boost problem.
Basically, I want to chop up a string where the substrings of interest are separated by commas, and shove those into a string vector. This results in errors in g++, but it works fine compiling with Visual Studio
This program illustrates the issue exactly:
#include <boost/algorithm/string.hpp>
#include <string>
#include <vector>
int main (void) {
std::vector<std::string> str_vec;
std::string str_to_split = "this,is,the,string,to,split";
boost::algorithm::split(str_vec,
str_to_split.substr(1, str_to_split.size()-2),
boost::algorithm::is_any_of(","),
boost::algorithm::token_compress_on);
return 0;
}
To compile I do: >> g++ -o foo foo.cpp
This is my terminal output:
foo.cpp: In function 'int main()':
foo.cpp:11:54: error: invalid initialization of non-const reference type 'std::basic_string<char>&' from an rvalue of type'std::basic_string<char>'
boost::algorithm::split(str_vec,str_to_split.substr(1, str_to_split.size()-2),boost::algorithm::is_an
^
In file included from /usr/include/boost/algorithm/string.hpp:23:0,
from foo.cpp:1:
/usr/include/boost/algorithm/string/split.hpp:140:35: note: initializing argument 2 of 'equenceSequenceT& boost::algorithm::split(SequenceSequenceT&, RangeT&, PredicateT, boost::algorithm::token_compress_mode_type) [with SequenceSequenceT = std::vector<std::basic_string<char> >; RangeT = std::basic_string<char>; PredicateT = boost::algorithm::detail::is_any_ofF<char>]'
inline SequenceSequenceT& split(
^
This function takes std::string& rather than std::string or const std::string&. That means you'll have to store the result of .substr in an intermediate variable then pass the variable to boost::algorithm::split. It'll be clearer code anyway.
FWIW, I have no idea why the function is designed this way. Seems odd to me but there you go.
I have a problem when attempting to use std::map in clang-3.3 and clang-3.0 on Ubuntu 12.04:
#include <iostream>
#include <map>
#include <string>
class A
{
public:
#if 0 //clang compiles ok
typedef std::map<std::string,std::string> MapKeyValue_t;
void PrintMap(const MapKeyValue_t &my_map
= MapKeyValue_t())
#else // clang compiles fail
void PrintMap(const std::map<std::string,std::string> &my_map
= std::map<std::string,std::string>())
#endif
{
std::map<std::string,std::string>::const_iterator it;
for (it = my_map.begin(); it != my_map.end(); it++)
{
std::cout << it->first << " " << it->second << std::endl;
}
}
};
int main()
{
A a;
a.PrintMap();
return 0;
}
However, while the code compiles in both g++ and clang I keep getting these errors as output:
test.cpp:14:36: error: expected ')'
= std::map<std::string,std::string>())
^
test.cpp:13:15: note: to match this '('
void PrintMap(const std::map<std::string,std::string> &my_map
^
test.cpp:14:24: error: expected '>'
= std::map<std::string,std::string>())
^
test.cpp:28:13: error: too few arguments to function call, expected 2, have 0
a.PrintMap();
~~~~~~~~~~ ^
test.cpp:13:2: note: 'PrintMap' declared here
void PrintMap(const std::map<std::string,std::string> &my_map
^
3 errors generated.
The closest thing I could find that matches my problem is this topic: How to pass std::map as a default constructor parameter
But, I have no idea what's wrong. Hopefully, someone can shed some light on this, please.
Update:
void PrintMap(const std::map<std::string,std::string> &my_map
= (std::map<std::string,std::string>()))
is ok. Thanks.
I compiled and run it successfully in vs2012.
So I think it's compilers problem.
The other posters are correct, I think this is an instance of Bug 13657 which should be fixed in Clang 3.4.
As mentioned in the bug report and the C++ Standard Core Language Active Issues page linked from there (and as you mentioned in your update), you can work around the issue by adding parentheses to the default value as follows:
void PrintMap(const std::map<std::string,std::string> &my_map
= (std::map<std::string,std::string>()))
Going by the opening paragraph of the boost::spirit::qi::symbols documentation, I assumed that it wouldn't be too hard to add symbols to a qi::symbols from a semantic action. Unfortunately it appears to be not as straightforward as I would have assumed.
The following bit of test code exhibits the problem:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
typedef qi::symbols<char, unsigned int> constants_dictionary;
template <typename Iter> struct parser : public qi::grammar<Iter, qi::space_type> {
parser(constants_dictionary &dict) : parser::base_type(start) {
start = qi::lit("#") >> ((+qi::char_) >> qi::uint_)[dict.add(qi::_1, qi::_2)];
}
qi::rule<Iter> start;
};
int main() {
constants_dictionary dict;
parser<std::string::const_iterator> prsr(dict);
std::string test = "#foo 3";
parse(test.begin(), test.end(), prsr, qi::space);
}
Gives type errors related to qi::_2 from VS2010:
C:\Users\k\Coding\dashCompiler\spirit_test.cpp(12) : error C2664: 'const boost::
spirit::qi::symbols<Char,T>::adder &boost::spirit::qi::symbols<Char,T>::adder::o
perator ()<boost::spirit::_1_type>(const Str &,const T &) const' : cannot conver
t parameter 2 from 'const boost::spirit::_2_type' to 'const unsigned int &'
with
[
Char=char,
T=unsigned int,
Str=boost::spirit::_1_type
]
Reason: cannot convert from 'const boost::spirit::_2_type' to 'const uns
igned int'
No user-defined-conversion operator available that can perform this conv
ersion, or the operator cannot be called
C:\Users\k\Coding\dashCompiler\spirit_test.cpp(10) : while compiling cla
ss template member function 'parser<Iter>::parser(constants_dictionary &)'
with
[
Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
]
C:\Users\k\Coding\dashCompiler\spirit_test.cpp(21) : see reference to cl
ass template instantiation 'parser<Iter>' being compiled
with
[
Iter=std::_String_const_iterator<char,std::char_traits<char>,std::al
locator<char>>
]
(Apologies for the nasty VS2010 error-style)
What syntax am I supposed to be using to add (and later on, remove) symbols from this table?
This question has been answered before. However, there is quite a range of problems with your posted code, so I'll fix them up one by one to spare you unnecessary staring at pages of error messages.
The working code (plus verification of output) is here on liveworkspace.org.
Notes:
the semantic action must be a Phoenix actor, i.e. you need
boost::bind, phoenix::bind, std::bind
phoenix::lambda<> or phoenix::function<>
a function pointer or polymorphic calleable object (as per the documentation)
I'd recommend phoenix::bind (in this particular case), which I show below
There was a mismatch between the parser's skipper and the start rule
qi::char_ eats all characters. Combined with the skipper, this resulted
in parse failure, because (obviously) the digits in the value were also being
eaten by +qi::char_. I show you one of many solutions, based on qi::lexeme[+qi::graph]
use qi::lexeme to 'bypass' the skipper (i.e. to prevent +qi::graph to cut
across whitespace because the skipper, well, skipped it)
qi::parse doesn't take a skipper; use qi::phrase_parse for that (the
reason it appeared to work is that any trailing 'variadic' arguments are
bound to the exposed attributes of the parser, which in this case are
unspecified, and therefore qi::unused_type).
if you want to pass test.begin() and test.end() directly to
qi::phrase_parse, you need to make it clear that you want const iterators. The
more typical solution would be to introduce explicitely typed variables
(first and last, e.g.)
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef qi::symbols<char, unsigned int> constants_dictionary;
template <typename Iter> struct parser : qi::grammar<Iter, qi::space_type>
{
parser(constants_dictionary &dict) : parser::base_type(start)
{
start = qi::lit("#") >> (qi::lexeme [+qi::graph] >> qi::uint_)
[ phx::bind(dict.add, qi::_1, qi::_2) ]
;
}
qi::rule<Iter, qi::space_type> start;
};
int main() {
constants_dictionary dict;
parser<std::string::const_iterator> prsr(dict);
const std::string test = "#foo 3";
if (qi::phrase_parse(test.begin(), test.end(), prsr, qi::space))
{
std::cout << "check: " << dict.at("foo") << "\n";
}
}