I have the following simple code:
#include <boost/program_options.hpp>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
namespace po = boost::program_options;
int main(int argc, char *argv[])
{
po::options_description config("Configuration");
config.add_options()
("optimization", po::value<int>()->default_value(10),
"optimization level")
("include-path,I",
po::value< vector<string> >()->composing(),
"include path")
;
po::variables_map vm;
po::store(po::parse_command_line(argc, argv, config), vm);
auto popts = po::parse_config_file<char>("config.ini",config,true);
po::store(popts,vm);
po::notify(vm);
for(auto o:popts.options) {
cout << o.string_key << "=" << "\n";
std::copy(o.value.begin(), o.value.end(), std::ostream_iterator<char>(std::cout, " "));
}
return 0;
}
Which I try to compile with gcc using:
g++ -std=c++11 test.cpp
This gives me the following error:
In file included from /usr/include/c++/6.2.1/bits/char_traits.h:39:0,
from /usr/include/c++/6.2.1/string:40,
from /usr/include/boost/program_options/errors.hpp:12,
from /usr/include/boost/program_options/options_description.hpp:12,
from /usr/include/boost/program_options.hpp:15,
from test.cpp:1:
/usr/include/c++/6.2.1/bits/stl_algobase.h: In instantiation of ‘static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = std::__cxx11::basic_string<char>*; _OI = std::ostream_iterator<char>]’:
/usr/include/c++/6.2.1/bits/stl_algobase.h:386:44: required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = std::__cxx11::basic_string<char>*; _OI = std::ostream_iterator<char>]’
/usr/include/c++/6.2.1/bits/stl_algobase.h:422:45: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _OI = std::ostream_iterator<char>]’
/usr/include/c++/6.2.1/bits/stl_algobase.h:455:8: required from ‘_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > >; _OI = std::ostream_iterator<char>]’
test.cpp:33:96: required from here
/usr/include/c++/6.2.1/bits/stl_algobase.h:324:18: error: no match for ‘operator=’ (operand types are ‘std::ostream_iterator<char>’ and ‘std::__cxx11::basic_string<char>’)
*__result = *__first;
~~~~~~~~~~^~~~~~~~~~
In file included from /usr/include/c++/6.2.1/iterator:66:0,
from /usr/include/boost/detail/iterator.hpp:11,
from /usr/include/boost/iterator/iterator_traits.hpp:8,
from /usr/include/boost/range/iterator_range_core.hpp:26,
from /usr/include/boost/lexical_cast.hpp:30,
from /usr/include/boost/program_options/value_semantic.hpp:14,
from /usr/include/boost/program_options/options_description.hpp:13,
from /usr/include/boost/program_options.hpp:15,
from test.cpp:1:
/usr/include/c++/6.2.1/bits/stream_iterator.h:193:7: note: candidate: std::ostream_iterator<_Tp, _CharT, _Traits>& std::ostream_iterator<_Tp, _CharT, _Traits>::operator=(const _Tp&) [with _Tp = char; _CharT = char; _Traits = std::char_traits<char>]
operator=(const _Tp& __value)
^~~~~~~~
/usr/include/c++/6.2.1/bits/stream_iterator.h:193:7: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘const char&’
/usr/include/c++/6.2.1/bits/stream_iterator.h:154:11: note: candidate: std::ostream_iterator<char>& std::ostream_iterator<char>::operator=(const std::ostream_iterator<char>&)
class ostream_iterator
^~~~~~~~~~~~~~~~
/usr/include/c++/6.2.1/bits/stream_iterator.h:154:11: note: no known conversion for argument 1 from ‘std::__cxx11::basic_string<char>’ to ‘const std::ostream_iterator<char>&’
What am I missing? Is this some kind of ABI incompatibility ?
I'm using gcc 6.2.1 and boost 1.61.
(Note: Yes I need to link the boost libraries as well, but the problem here is the compiler error.)
Found the error myself.
Instead of
std::copy(o.value.begin(), o.value.end(), std::ostream_iterator<char>(std::cout, " "));
it should have been
std::copy(o.value.begin(), o.value.end(), std::ostream_iterator<string>(std::cout, " "));
(Wrong template parameter char instead of string).
Related
I am trying to parse a optional list of things followed by a semicolon (this is a simplified example). Below is a example program:
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <iostream>
#include <optional>
#include <string>
#include <vector>
namespace x3=boost::spirit::x3;
namespace ast
{
struct doubleOrString : x3::variant<double,std::string>{
using base_type::base_type;
using base_type::operator=;
};
struct pass {
std::vector<doubleOrString> dOrs;
};
}//ast namespace
BOOST_FUSION_ADAPT_STRUCT(ast::pass,dOrs)
x3::rule<class doubleOrString_class, ast::doubleOrString> const doubleOrString = "doubleOrString";
x3::rule<class pass_class, ast::pass> const pass = "pass";
x3::rule<class es_class, std::optional<ast::pass>> const es = "es";
auto const doubleOrString_def =x3::double_ | x3::string("AString");
auto const pass_def = doubleOrString % x3::lit(",");
auto const es_def = (pass > x3::lit(";")) | x3::lit(";");
BOOST_SPIRIT_DEFINE(doubleOrString,pass,es);
int main()
{
using boost::spirit::x3::ascii::space;
typedef std::string::const_iterator iterator_type;
std::string str;
while (getline(std::cin, str))
{
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
std::optional<ast::pass> esdOrs;
iterator_type iter = str.begin();
iterator_type const end = str.end();
bool r = phrase_parse(iter, end, es, space, esdOrs);
if (r && iter == end)
{
std::cout << "\nGood!\n";
}
else
{
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "-------------------------\n";
}
}
std::cout << "Bye... :-) \n\n";
return 0;
}
However it fails to compile with the error:
usr/include/boost/spirit/home/x3/support/ast/variant.hpp:184:17: error: no match for ‘operator=’ (operand types are ‘boost::spirit::x3::variant<double, std::__cxx11::basic_string<char, std::char_traits, std::allocator<cha
r> > >::variant_type’ {aka ‘boost::variant<double, std::__cxx11::basic_string<char, std::char_traits, std::allocator > >’} and ‘std::optionalclient::ast::pass’)
26 184 | var = std::forward(rhs);
What am I doing wrong? The error is not very informative. It seems to work fine if I just do a optional of things.
I am using the following command (the file name is r1.cpp):
g++ --std=c++17 r1.cpp -o r1
With the following MRE(Minimal Reproducible Example):
#include <vector>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
namespace x3=boost::spirit::x3;
namespace ast
{
struct doubleOrString : x3::variant<double,std::string>{
using base_type::base_type;
using base_type::operator=;
};
struct pass {
std::vector<doubleOrString> dOrs;
};
}//ast namespace
BOOST_FUSION_ADAPT_STRUCT(ast::pass,dOrs)
x3::rule<class doubleOrString_class, ast::doubleOrString> const doubleOrString = "doubleOrString";
x3::rule<class pass_class, ast::pass> const pass = "pass";
x3::rule<class es_class, std::optional<ast::pass>> const es = "es";
auto const doubleOrString_def =x3::double_ | x3::string("AString");
auto const pass_def = doubleOrString % x3::lit(",");
auto const es_def = (pass > x3::lit(";")) | x3::lit(";");
BOOST_SPIRIT_DEFINE(doubleOrString,pass,es);
I get no compiler errors.
Please provide an MRE showing the error.
I'm building a custom cMessage that includes vectors as some fields. I have no issue with int or double vectors, but with string vectors, I get an error. Below is a sample message definition to reproduce the issue.
cplusplus {{
#include <vector>
typedef std::vector<int> IntVector;
typedef std::vector<string> StrVector;
}};
class IntVector { #existingClass; };
class StrVector { #existingClass; };
message sampleMessage extends cMessage
{
IntVector SampleIntVector;
StrVector SampleStrVector;
}
In my code, I have the below block
sampleMessage *msg = new sampleMessage();
vector<int> intVect = {1,2};
vector<string> stringVect;
string inputString = "dummy string";
stringVect.push_back(inputString);
msg->setSampleIntVector(intVect);
msg->setSampleStrVector(stringVect);
Using OMNeT++ version 6.0 pre10, at the 7th line, I get the error below suggesting the cMessage is expecting a vector<char *>
error: no viable conversion from 'vector<std::string>' to 'const vector<char *>'
I also tried on OMNeT++ version 5.6.2 and got a different error message. For clarity, the file testModel_m.cc is generated by OMNeT++.
testModel_m.cc:170:13: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::ostream' (aka 'basic_ostream<char>') and 'const std::__cxx11::basic_string<char>')
out << *it;
~~~ ^ ~~~
testModel_m.cc:2040:45: note: in instantiation of function template specialization 'operator<<<std::__cxx11::basic_string<char>, std::allocator<std::__cxx11::basic_string<char> > >' requested here
case 1: {std::stringstream out; out << pp->getSampleStrVector(); return out.str();}
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:6416:5: note: candidate function [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
operator<<(basic_ostream<_CharT, _Traits>& __os,
^
testModel_m.cc:158:22: note: candidate function [with T = std::__cxx11::basic_string<char>]
inline std::ostream& operator<<(std::ostream& out,const T&) {return out;}
If I change the vector to char *, it works, but for my use case, I would need a vector of string since I search for values in a vector and with char *, that doesn't work quite well.
Is there a way to have a vector<string> field as part of the custom cMessage?
The workaround for the error use of overloaded operator '<<' is ambiguous is adding own definition of operator<< inside cplusplus {{ }} block, for example:
cplusplus {{
#include <vector>
typedef std::vector<int> IntVector;
typedef std::vector<std::string> StrVector;
std::ostream& operator<<(std::ostream &os, const StrVector& vec) {
std::stringstream out;
for (auto i : vec) {
out << i << ", ";
}
return os << out.str();
};
}};
class IntVector { #existingClass; };
class StrVector { #existingClass; };
message sampleMessage {
IntVector SampleIntVector;
StrVector SampleStrVector;
}
Here is my code:
#include <cstdint>
#include <vector>
class Bar {
uint32_t m_value;
public:
Bar(const uint32_t value) : m_value(value) {
}
};
class Foo {
Bar* m_p_bar;
uint32_t m_value;
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo& operator=(Foo&&) = default;
Foo(Foo&&) = default;
public:
/*
Foo(Foo&& from) {
m_p_bar = from.m_p_bar;
m_value = from.m_value;
from.m_p_bar = nullptr;
}
*/
Foo(const uint32_t value) : m_value(value) {
m_p_bar = new Bar(value);
}
};
int main() {
std::vector<Foo> foos;
foos.emplace_back(8);
}
Compiler complains:
In file included from /opt/rh/devtoolset-9/root/usr/include/c++/9/vector:66,
from test_implicit_func.cpp:2:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h: In instantiation of ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*]’:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:307:37: required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<Foo*>; _ForwardIterator = Foo*; _Tp = Foo]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:329:2: required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = Foo*; _ForwardIterator = Foo*; _Allocator = std::allocator<Foo>]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:474:3: required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Foo*, std::vector<Foo> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Foo*]’
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/vector.tcc:121:4: required from ‘std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {int}; _Tp = Foo; _Alloc = std::allocator<Foo>; std::vector<_Tp, _Alloc>::reference = Foo&]’
test_implicit_func.cpp:34:21: required from here
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
127 | static_assert(is_constructible<_ValueType2, decltype(*__first)>::value,
| ^~~~~
I noticed that for some reason, I need to define my own move constructor for Foo. By explicitly asking the compiler to use the default one (i.e. Foo(Foo&&) = default;), it doesn't work. However, if I ask the compiler to use all the implicit ones (i.e. removing Foo(const Foo&) = delete; Foo& operator=(const Foo&) = delete; Foo& operator=(Foo&&) = default; Foo(Foo&&) = default;), then compiler doesn't complain.
My question is why explicitly asking compiler to use the default move constructor here doesn't work but it works in this case. And this answer suggests I could ask for a default version if it is implicitly removed.
If you let the compiler use the implicitly defined "big 5" you will have problems with leaks and double free:s.
You need to make the move constructor public and you need to delete the pointer in the destructor. You also need to make sure not to leave the pointer in the moved-from object.
#include <utility> // exchange
class Foo {
Bar* m_p_bar;
uint32_t m_value;
public:
Foo(const uint32_t value) :
m_p_bar(new Bar(value)),
m_value(value)
{}
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
Foo(Foo&& rhs) :
m_p_bar(std::exchange(rhs.m_p_bar, nullptr)), // put a nullptr in rhs
m_value(rhs.m_value)
{}
Foo& operator=(Foo&& rhs) {
std::swap(m_p_bar, rhs.m_p_bar); // let rhs destroy our current Bar
m_value = rhs.m_value;
return *this;
}
~Foo() { delete m_p_bar; } // destroy it
};
A better idea would be to use a std::unique_ptr<Bar> - or to not use a pointer at all.
I have the following piece of code -
#include <map>
using Type1 = std::map<std::string, unsigned long long>;
using Type2 = std::map<std::string, Type1>;
class T
{
private:
Type2 mymap;
public:
const Type1& get(const std::string& key) const;
};
const Type1& T::get(const std::string& key) const
{
return mymap[key];
}
int main(void)
{
}
This does not compile and the compiler complains -
maps.cpp: In member function ‘const Type1& T::get(const string&)
const’: maps.cpp:17:20: error: passing ‘const Type2 {aka const
std::map<std::basic_string<char>, std::map<std::basic_string<char>,
long long unsigned int> >}’ as ‘this’ argument of ‘std::map<_Key, _Tp,
_Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const key_type&) [with _Key = std::basic_string<char>; _Tp = std::map<std::basic_string<char>, long
long unsigned int>; _Compare = std::less<std::basic_string<char> >;
_Alloc = std::allocator<std::pair<const std::basic_string<char>, std::map<std::basic_string<char>, long long unsigned int> > >;
std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type =
std::map<std::basic_string<char>, long long unsigned int>;
std::map<_Key, _Tp, _Compare, _Alloc>::key_type =
std::basic_string<char>]’ discards qualifiers [-fpermissive]
return mymap[key];
^
I need help understanding this error. From what I can tell I am not modifying "this" in the get function.
Thanks!
The errors comes from the fact that
std::map::operator[] can
inserts the key if the it does not exist.
You could do a std::map::find first as a check.
I'm trying to read from a const std::vector to an std::istream, but everything I've tried runs into the problem with const.
This version compiles perfectly:
#include <vector>
#include <iostream>
template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
vectorbuf(std::vector<char>& v) {
this->setg(v.data(), v.data(), v.data()+v.size());
}
};
void doStuff(std::vector<char>& v) {
vectorbuf<> vbuff(v);
std::istream s(&vbuff);
}
int main(int argc, char** argv) {
std::vector<char> v = {'a', 'b', 'c'};
doStuff(v);
return 0;
}
while this produces errors:
#include <vector>
#include <iostream>
template<typename CharT = char, typename TraitsT = std::char_traits<CharT> >
class const_vectorbuf : public std::basic_streambuf<CharT, TraitsT> {
public:
const_vectorbuf(const std::vector<char>& v) {
this->setg(v.data(), v.data(), v.data()+v.size());
}
};
void const_doStuff(const std::vector<char>& v) {
const_vectorbuf<const char> vbuff(v);
//std::istream s(&vbuff); With this commented out I get the error below
}
int main(int argc, char** argv) {
std::vector<char> v = {'a', 'b', 'c'};
const_doStuff(v);
return 0;
}
And I'm not sure how to fix it.
The error:
In file included from /usr/include/c++/4.8/ios:40:0,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from vector_stream.cpp:2:
/usr/include/c++/4.8/bits/char_traits.h: In instantiation of ‘static void __gnu_cxx::char_traits<_CharT>::assign(__gnu_cxx::char_traits<_CharT>::char_type&, const char_type&) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char]’:
/usr/include/c++/4.8/bits/streambuf.tcc:67:63: required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1: required from here
/usr/include/c++/4.8/bits/char_traits.h:93:14: error: assignment of read-only reference ‘__c1’
{ __c1 = __c2; }
^
In file included from /usr/include/c++/4.8/vector:60:0,
from vector_stream.cpp:1:
/usr/include/c++/4.8/bits/stl_algobase.h: In instantiation of ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’:
/usr/include/c++/4.8/bits/stl_algobase.h:428:38: required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17: required from ‘_OI std::copy(_II, _II, _OI) [with _II = const char*; _OI = const char*]’
/usr/include/c++/4.8/bits/char_traits.h:192:39: required from ‘static __gnu_cxx::char_traits<_CharT>::char_type* __gnu_cxx::char_traits<_CharT>::copy(__gnu_cxx::char_traits<_CharT>::char_type*, const char_type*, std::size_t) [with _CharT = const char; __gnu_cxx::char_traits<_CharT>::char_type = const char; std::size_t = long unsigned int]’
/usr/include/c++/4.8/bits/streambuf.tcc:56:50: required from ‘std::streamsize std::basic_streambuf<_CharT, _Traits>::xsgetn(std::basic_streambuf<_CharT, _Traits>::char_type*, std::streamsize) [with _CharT = const char; _Traits = std::char_traits<const char>; std::streamsize = long int; std::basic_streambuf<_CharT, _Traits>::char_type = const char]’
vector_stream.cpp:36:1: required from here
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: error: no matching function for call to ‘std::__copy_move<false, true, std::random_access_iterator_tag>::__copy_m(const char*&, const char*&, const char*&)’
_Category>::__copy_m(__first, __last, __result);
^
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: candidate is:
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template<class _Tp> static _Tp* std::__copy_move<_IsMove, true, std::random_access_iterator_tag>::__copy_m(const _Tp*, const _Tp*, _Tp*) [with _Tp = _Tp; bool _IsMove = false]
__copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result)
^
/usr/include/c++/4.8/bits/stl_algobase.h:368:9: note: template argument deduction/substitution failed:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70: note: deduced conflicting types for parameter ‘_Tp’ (‘char’ and ‘const char’)
_Category>::__copy_m(__first, __last, __result);
So despite CharT being const char streambuf_type is still char, I've been looking and so far I haven't found a way to change that. The assignment __c1 = __c2 in char_traits I haven't had the time to even begin look at a way to solve yet.
I feel quite certain that basic_streambuf requires it's first template to be not-const. Also, I think basic_streambuf requires write access, because the basic_streambuf manages both in and out, regardless of what you use it for in the end. You should probably also override some other members to cause writes to fail: sputbackc, sungetc, sputc, sputn, xsputn...
§ 27.2.2/2 In the classes of Clause 27, a template formal parameter with name charT represents a member of the set of types containing char, wchar_t, and any other implementation-defined character types that satisfy the requirements for a character on which any of the iostream components can be instantiated.
(emphsis mine) This rule is a little vague, but I'm pretty sure it clearly covers your case.