making shared_ptr's from Boost.Spirit.Qi - c++

I would like to use a Spirit Qi grammar to parse text into shared pointers to strings. Actually, I would like to parse multivariate polynomials into a system of them, with various kinds of previously-encountered symbols appearing in the polynomials, but for now, let's parse from text into std::shared_ptr<std::string>.
I have been floundering for a long time now, and have distilled this small test grammar in a header file:
#define BOOST_SPIRIT_USE_PHOENIX_V3 1
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/bind.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template<typename Iterator>
struct SharedPtrParser : qi::grammar<Iterator, std::shared_ptr<std::string>(), boost::spirit::ascii::space_type>
{
SharedPtrParser() : SharedPtrParser(startrule)
{
startrule = qi::eps[ qi::_val = std::make_shared<std::string>()];
}
qi::rule<Iterator,std::shared_ptr<std::string>()> startrule;
};
and this usage of it in main:
#include "shared_ptr_test.h"
int main()
{
SharedPtrParser<std::string::const_iterator> C;
std::string text = "thisissometext";
auto iter = text.begin();
auto end = text.end();
std::shared_ptr<std::string> S;
bool s = phrase_parse(iter, end, C,boost::spirit::ascii::space, S);
return 0;
}
I am aware that my grammar doesn't do squat. I just want to make shared pointers from Qi right now! To this end, I've found a number of hints regarding using smart pointers in conjunction with Qi, but no grammars which are factories for them. I feel like I've been close, especially having found this post by sehe from Spirit General discussion forum. However, I just haven't been able to put it together yet.
Attempts at compilation produce two errors as written ATM.
one:
./shared_ptr_test.h:16:22: error: no matching constructor for initialization of 'SharedPtrParser<std::__1::__wrap_iter<const char *> >'
SharedPtrParser() : SharedPtrParser(startrule)
^ ~~~~~~~~~
shared_ptr_test.cpp:8:47: note: in instantiation of member function 'SharedPtrParser<std::__1::__wrap_iter<const char *> >::SharedPtrParser' requested here
SharedPtrParser<std::string::const_iterator> C;
^
./shared_ptr_test.h:14:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'qi::rule<__wrap_iter<const char *>,
std::shared_ptr<std::string> ()>' to 'const SharedPtrParser<std::__1::__wrap_iter<const char *> >' for 1st argument
struct SharedPtrParser : qi::grammar<Iterator, std::shared_ptr<std::string>(), boost::spirit::ascii::space_type>
^
./shared_ptr_test.h:16:2: note: candidate constructor not viable: requires 0 arguments, but 1 was provided
SharedPtrParser() : SharedPtrParser(startrule)
^
two:
In file included from shared_ptr_test.cpp:1:
In file included from ./shared_ptr_test.h:4:
In file included from /usr/local/include/boost/spirit/include/qi.hpp:16:
In file included from /usr/local/include/boost/spirit/home/qi.hpp:21:
In file included from /usr/local/include/boost/spirit/home/qi/nonterminal.hpp:14:
In file included from /usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:35:
/usr/local/include/boost/spirit/home/qi/reference.hpp:43:30: error: no matching member function for call to 'parse'
return ref.get().parse(first, last, context, skipper, attr_);
~~~~~~~~~~^~~~~
/usr/local/include/boost/spirit/home/qi/parse.hpp:164:40: note: in instantiation of function template specialization 'boost::spirit::qi::reference<const
boost::spirit::qi::rule<std::__1::__wrap_iter<const char *>, std::__1::shared_ptr<std::__1::basic_string<char> > (),
boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >::parse<std::__1::__wrap_iter<char *>,
boost::spirit::context<boost::fusion::cons<std::__1::shared_ptr<std::__1::basic_string<char> > &, boost::fusion::nil_>, boost::spirit::locals<mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, std::__1::shared_ptr<std::__1::basic_string<char> > >' requested here
if (!compile<qi::domain>(expr).parse(
^
/usr/local/include/boost/spirit/home/qi/parse.hpp:197:20: note: in instantiation of function template specialization 'boost::spirit::qi::phrase_parse<std::__1::__wrap_iter<char *>,
SharedPtrParser<std::__1::__wrap_iter<const char *> >, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, std::__1::shared_ptr<std::__1::basic_string<char>
> >' requested here
return qi::phrase_parse(first, last, expr, skipper, skip_flag::postskip, attr);
^
shared_ptr_test.cpp:18:11: note: in instantiation of function template specialization 'boost::spirit::qi::phrase_parse<std::__1::__wrap_iter<char *>,
SharedPtrParser<std::__1::__wrap_iter<const char *> >, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0>, std::__1::shared_ptr<std::__1::basic_string<char>
> >' requested here
bool s = phrase_parse(iter, end, C,boost::spirit::ascii::space, S);
^
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:274:14: note: candidate function [with Context =
boost::spirit::context<boost::fusion::cons<std::__1::shared_ptr<std::__1::basic_string<char> > &, boost::fusion::nil_>, boost::spirit::locals<mpl_::na, mpl_::na, mpl_::na,
mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space,
boost::spirit::char_encoding::ascii> >, Attribute = std::__1::shared_ptr<std::__1::basic_string<char> >] not viable: no known conversion from 'std::__1::__wrap_iter<char *>' to
'std::__1::__wrap_iter<const char *> &' for 1st argument
bool parse(Iterator& first, Iterator const& last
^
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:320:14: note: candidate function template not viable: requires 6 arguments, but 5 were provided
bool parse(Iterator& first, Iterator const& last
A little help?

My problem here was trivial and noobish. I failed to specify for the constructor, ::base_type. That is, the line for SharedPtrParser() : SharedPtrParser(startrule) should have been SharedPtrParser() : SharedPtrParser::base_type(startrule).

Related

Do const class methods prevent assigning variables outside of the class?

I have solved the problem of getting this code to compile by removing the "const". However, why does it seem I cannot assign non-class members in a const class method in this specific situation? It probably is part of the class; though, I do not understand why.
I got my code to compile, but I am confused at this situation.
Below, are some declarations in the class.
using twoDList = multimap<string,string>;
twoDList SomeMultiMap;
This will work when I take off the "const". Or at least compile. Though, here I am just assigning iterators declared only in this function. Using namespace std by the way.
bool object::foo(string a, string b) const
{
pair<object::twoDList::iterator,object::twoDList::iterator> wordRange;
wordRange = SomeMultiMap.equal_range(a);
object::twoDList::iterator it = wordRange.first;
//...
//...
//...
}
I expected this function to compile without removing the const, but it does not compile.
Edit: here are the compilation errors, and I am using this on linux command line.
g++ -g -DDEBUG -std=c++11 -c test1.cpp
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:64:0,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from test1.cpp:1:
/usr/include/c++/4.8/bits/stl_pair.h: In instantiation of ‘std::pair<_T1, _T2>& std::pair<_T1, _T2>::operator=(std::pair<_U1, _U2>&&) [with _U1 = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _U2 = std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _T1 = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >; _T2 = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >]’:
test1.cpp:15:15: required from here
/usr/include/c++/4.8/bits/stl_pair.h:188:10: error: no match for ‘operator=’ (operand types are ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ and ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’)
first = std::forward<_U1>(__p.first);
^
/usr/include/c++/4.8/bits/stl_pair.h:188:10: note: candidates are:
In file included from /usr/include/c++/4.8/map:60:0,
from test1.cpp:2:
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >& std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >::operator=(const std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&)
struct _Rb_tree_iterator
^
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ to ‘const std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&’
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >& std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >::operator=(std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&&)
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ to ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&&’
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:64:0,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from test1.cpp:1:
/usr/include/c++/4.8/bits/stl_pair.h:189:11: error: no match for ‘operator=’ (operand types are ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ and ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’)
second = std::forward<_U2>(__p.second);
^
/usr/include/c++/4.8/bits/stl_pair.h:189:11: note: candidates are:
In file included from /usr/include/c++/4.8/map:60:0,
from test1.cpp:2:
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >& std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >::operator=(const std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&)
struct _Rb_tree_iterator
^
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ to ‘const std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&’
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >& std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >::operator=(std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&&)
/usr/include/c++/4.8/bits/stl_tree.h:157:12: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >’ to ‘std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::basic_string<char> > >&&’
makefile:10: recipe for target 'test1.o' failed
make: *** [test1.o] Error 1
Edit: more edits to fix scope operators. Also, added the fact that I am using namespace std if that helps.
A const after a member function's parameter list is a promise not to change the class object via the this pointer. The type of this becomes const ClassType* instead of just ClassType*. (Like any pointer-to-const or reference-to-const, this only means the thing can't be changed using that pointer or reference, not that the object is permanently const or can't be changed by other means.)
To say a class object is treated as const means that all its members (except any marked mutable) are treated as const. And since in a member function definition a plain non-static member name N actually means the same as this->N, members named that way are treated as const when the function declaration has a const after the parameter list.
So inside bool object::foo(string a, string b) const, the name SomeMultiMap, being a member of object, is treated as a const SomeMultiMap. And equal_range gives a pair<const_iterator, const_iterator> when the multimap object expression is const, or a pair<iterator, iterator> only when the object expression is not const.
So this may work instead (depending on what you need to do afterward):
std::pair<twoDList::const_iterator,twoDList::const_iterator> wordRange;
wordRange = SomeMultiMap.equal_range(a);
twoDList::const_iterator it = wordRange.first;
(Note you usually don't need the object:: prefixes, since the member function body is in its class's scope.)
Although I would just define these variables with auto instead, avoiding the need to get the type exactly right, and saving on typing out those long iterator names.
auto wordRange = SomeMultiMap.equal_range(a);
auto it = wordRange.first;

difference between unordered_map<const T, int> and map<const T, int>

#include <string>
#include <map>
#include <unordered_map>
using namespace std;
class Solution {
public:
private:
// unordered_map<string, int> mapStrInt; // Case 1: OK
// unordered_map<const string, int> mapStrInt; // Case 2: Fail
// map<string, int> mapStrInt; // Case 3: OK
// map<const string, int> mapStrInt; // Case 4: OK
};
Question> Why Case 2 is not legal?
template < class Key, // unordered_map::key_type
class T, // unordered_map::mapped_type
class Hash = hash<Key>, // unordered_map::hasher
class Pred = equal_to<Key>, // unordered_map::key_equal
class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type
> class unordered_map;
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > // map::allocator_type
> class map;
Based on http://www.compileonline.com/compile_cpp11_online.php
Compiling the source code....
$g++ -std=c++11 main.cpp -o demo -lm -pthread -lgmpxx -lgmp -lreadline 2>&1
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:3:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::_Hash_code_base<const std::basic_string<char>, std::pair<const std::basic_string<char>, int>, std::__detail::_Select1st, std::hash<const std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>':
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1402:10: required from 'struct std::__detail::_Hashtable_base<const std::basic_string<char>, std::pair<const std::basic_string<char>, int>, std::__detail::_Select1st, std::equal_to<const std::basic_string<char> >, std::hash<const std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits<true, false, true> >'
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:174:11: required from 'class std::_Hashtable<const std::basic_string<char>, std::pair<const std::basic_string<char>, int>, std::allocator<std::pair<const std::basic_string<char>, int> >, std::__detail::_Select1st, std::equal_to<const std::basic_string<char> >, std::hash<const std::basic_string<char> >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >'
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/unordered_map.h:100:18: required from 'class std::unordered_map<const std::basic_string<char>, int>'
main.cpp:11:38: required from here
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type 'struct std::hash<const std::basic_string<char> >'
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/basic_string.h:3033:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/string:52,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/functional_hash.h:58:12: error: declaration of 'struct std::hash<const std::basic_string<char> >'
struct hash;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:3:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1070:12: error: invalid use of incomplete type 'struct std::hash<const std::basic_string<char> >'
struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/basic_string.h:3033:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/string:52,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/functional_hash.h:58:12: error: declaration of 'struct std::hash<const std::basic_string<char> >'
struct hash;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:3:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type 'struct std::hash<const std::basic_string<char> >'
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/basic_string.h:3033:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/string:52,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/functional_hash.h:58:12: error: declaration of 'struct std::hash<const std::basic_string<char> >'
struct hash;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable.h:35:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/unordered_map:47,
from main.cpp:3:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/hashtable_policy.h:1082:53: error: invalid use of incomplete type 'struct std::hash<const std::basic_string<char> >'
using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
^
In file included from /usr/local/gcc-4.8.1/include/c++/4.8.1/bits/basic_string.h:3033:0,
from /usr/local/gcc-4.8.1/include/c++/4.8.1/string:52,
from main.cpp:1:
/usr/local/gcc-4.8.1/include/c++/4.8.1/bits/functional_hash.h:58:12: error: declaration of 'struct std::hash<const std::basic_string<char> >'
struct hash;
^
== Updated Working code based on the comments ==
struct HashConstString
{
long operator()(const string& str) const {
return hash<string>()(str);
}
};
class Solution {
public:
private:
unordered_map<const string, int, HashConstString> mapStrInt; // Case 2: Now it works
};
From 21.6 we learn that four string-related hash functions are provided by the language:
template <> struct hash<string>;
template <> struct hash<u16string>;
template <> struct hash<u32string>;
template <> struct hash<wstring>;
Then from 23.5.2 we learn that the default hash for unordered_map is hash<Key> or in this case hash<const std::string>. Previously we learned that the implementation is not required to provide such a hash, so your code is not guaranteed to compile.
template <class Key,
class T,
class Hash = hash<Key>,
class Pred = std::equal_to<Key>,
class Alloc = std::allocator<std::pair<const Key, T> > >
class unordered_map;
You can either use std::string as your key OR specify the hash function as hash<std::string> instead of relying on the default template parameter.

No match found for operator= (find value in vector<string>)

I'm clearly missing something here, but what?
Definition (... denotes valid code, not actual three points):
class CrmxFile {
private:
const std::vector<std::string> validValues;
int value;
public:
void setValue(std::string _value);
...
}
std::vector<std::string> CrmxFile = {...};
In the code I have this:
void Crmx::SetValue(std::string _value) {
std::vector<std::string>::iterator idx;
if((idx = std::find(validValues.begin(), validValues.end(), _value)) == validValues.end()) {
value = 0;
}
else {
value = idx - validValues.begin();
}
}
I compile this with gcc -c -std=c++0x and I get this error:
CrmxFile.cpp: In member function ‘void CrmxFile::SetValue(std::string)’:
CrmxFile.cpp:24:64: error: no match for ‘operator=’ in ‘idx = std::find [with _IIter = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, _Tp = std::basic_string<char>](Id3V1::validValues.std::vector<_Tp, _Alloc>::begin [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >, std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_pointer = const std::basic_string<char>*](), Id3V1::validValues.std::vector<_Tp, _Alloc>::end [with _Tp = std::basic_string<char>, _Alloc = std::allocator<std::basic_string<char> >, std::vector<_Tp, _Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >, typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::const_pointer = const std::basic_string<char>*](), (*(const std::basic_string<char>*)(& _value)))’
CrmxFile.cpp:24:64: note: candidates are:
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >& __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >::operator=(const __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&)
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >’ to ‘const __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&’
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >& __gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >::operator=(__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&&)
/usr/include/c++/4.6/bits/stl_iterator.h:702:11: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >’ to ‘__gnu_cxx::__normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >&&’
What am I missing? Or, alternatively, is there a better way of finding the index of a given value in a vector?
idx has to be a const_iterator since validValues is a const vector<...>.
std::vector<std::string>::const_iterator idx;
Since validValues is const, begin(), end(), and therefore this instantiation of std::find, all return std::vector<std::string>::const_iterator, not std::vector<std::string>::iterator. For const-safety, a const_iterator cannot convert to an iterator.
validValues is defined as const std::vector<std::string>. Therefore begin() and end() will return const_iterator, but you are trying to assign the result to a iterator. Converting a const_iterator to an iterator would break const correctness (since you could then go on and change the underlying object) and is therefore not allowed.
Change the definition of idx to be std::vector<std::string>::const_iterator and it should work.
"What am I missing?"
Is yours first validValues invalid?
I suggest:
void Crmx::SetValue(std::string _value) {
value = std::find(validValues.begin(), validValues.end(), _value) - validValues.begin();
}
and use the validValues.size as invalid value, not 0

Is this non-copyable map legal c++11? GCC 4.7 and MSVS 2010 allow it. Clang 3.1 does not

I have created a non-copyable map which I cannot get to compile with clang. Since clang is meant to be very standards compliant I was wondering if my code was legal. MSVS 2010 and GCC 4.7 compile this code without warnings or errors.
Full code is attached: the problematic line is the last line of main.
= delete needs removing for MSVS 2010
#include <utility>
#include <iostream>
#include <map>
template<typename Key_t, typename Value_t, typename Compare_t = std::less<Key_t> >
class non_copyable_map : public std::map<Key_t,Value_t,Compare_t>
{
typedef std::map<Key_t,Value_t,Compare_t> BaseType;
public:
non_copyable_map() { }
non_copyable_map(non_copyable_map&& t) : BaseType(std::move(t)) {}
non_copyable_map& operator = (non_copyable_map&& t)
{
if ( this != &t )
{
std::swap<BaseType>(*this,t);
}
return *this;
}
private:
non_copyable_map(const non_copyable_map&) = delete;
non_copyable_map& operator = (const non_copyable_map&) = delete;
};
int main(int argc, char* argv[])
{
non_copyable_map<int, non_copyable_map<int, int> > nestedMap;
non_copyable_map<int,int> inner;
inner[3]=4;
nestedMap[2] = std::move(inner); // THIS LINE CAUSES CLANG PROBLEMS
}
Error message when using clang++-mp-3.1 -std=c++0x -stdlib=libc++ MapOfMaps.cpp is:
In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:26:26: error: no type named '__storage_type' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
typedef typename _C::__storage_type __storage_type;
~~~~~~~~~~~~~^~~~~~~~~~~~~~
MapOfMaps.cpp:21:25: note: in instantiation of template class
'std::__1::__bit_reference<std::__1::map<int, int, std::__1::less<int>,
std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
std::swap<BaseType>(*this,t);
^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
std::__1::less<int> >::operator=' requested here
nestedMap[2] = std::move(inner);
^
In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:27:26: error: no type named '__storage_pointer' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
typedef typename _C::__storage_pointer __storage_pointer;
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__bit_reference:33:25: error: no type named '__self' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
friend typename _C::__self;
~~~~~~~~~~~~~^~~~~~
In file included from MapOfMaps.cpp:3:
In file included from /usr/include/c++/v1/map:338:
/usr/include/c++/v1/__tree:1291:14: error: overload resolution selected deleted operator '='
__pair3_ = _STD::move(__t.__pair3_);
~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__tree:1308:9: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
>::__move_assign' requested here
__move_assign(__t, true_type());
^
/usr/include/c++/v1/__tree:1353:5: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
>::__move_assign' requested here
__move_assign(__t, integral_constant<bool,
^
/usr/include/c++/v1/map:736:21: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> > >::operator='
requested here
__tree_ = _STD::move(__m.__tree_);
^
/usr/include/c++/v1/type_traits:2342:9: note: in instantiation of member function
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >::operator=' requested here
__x = _STD::move(__y);
^
MapOfMaps.cpp:21:5: note: in instantiation of function template specialization
'std::__1::swap<std::__1::map<int, int, std::__1::less<int>,
std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
std::swap<BaseType>(*this,t);
^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
std::__1::less<int> >::operator=' requested here
nestedMap[2] = std::move(inner);
^
/usr/include/c++/v1/memory:1918:7: note: candidate function (the implicit copy assignment
operator) has been explicitly deleted
class __compressed_pair
^
4 errors generated.
This may be a clang or libc++ bug (most likely libc++). I'm not duplicating your symptom with tip-of-trunk tools. The latest libc++ headers are here. This is a bit of a shot in the dark, but try this:
swap(static_cast<BaseType&>(*this),static_cast<BaseType&>(t));
It looks like you're getting tangled up with this swap in <__bit_reference>:
template <class _Cp, class _Dp>
_LIBCPP_INLINE_VISIBILITY inline
void
swap(__bit_reference<_Cp> __x, __bit_reference<_Dp> __y) _NOEXCEPT
which has nothing to do with maps. It just happens to be in scope.

strange template namespace problem

I've got a strange problem with templates and namespaces...
I have the following code which compiles fine..
using namespace boost::multi_index;
template < typename OT, typename KT, KT (OT::* KM)() const, typename KC, typename CMP >
class OrderBook
{
public:
OrderBook() {}
~OrderBook() {}
typedef multi_index_container<
OT,
indexed_by<
ordered_unique<
const_mem_fun< OT, KT, KM >,
KC
>,
ordered_unique<
identity< OT >,
CMP
>
>
> Container;
typedef typename Container::template nth_index< 0 >::type index_0;
typedef typename Container::template nth_index< 1 >::type index_1;
typedef typename index_0::const_iterator const_iterator_0;
typedef typename index_1::const_iterator const_iterator_1;
const_iterator_0 begin0() const { return _container.get<0>().begin(); }
const_iterator_0 end0() const { return _container.get<0>().end(); }
public:
Container _container;
};
However, due to a namespace collision when I insert this code into another project I have to have... (Notice how I've had to remove the using namespace boost::multi_index and manually specify it where needed
template < typename OT, typename KT, KT (OT::* KM)() const, typename KC, typename CMP >
class OrderBook
{
public:
OrderBook() {}
~OrderBook() {}
typedef boost::multi_index::multi_index_container<
OT,
boost::multi_index::indexed_by<
boost::multi_index::ordered_unique<
boost::multi_index::const_mem_fun< OT, KT, KM >,
KC
>,
boost::multi_index::ordered_unique<
boost::multi_index::identity< OT >,
CMP
>
>
> Container;
typedef typename Container::template nth_index< 0 >::type index_0;
typedef typename Container::template nth_index< 1 >::type index_1;
typedef typename index_0::const_iterator const_iterator_0;
typedef typename index_1::const_iterator const_iterator_1;
const_iterator_0 begin0() const { return _container.get<0>().begin(); }
const_iterator_0 end0() const { return _container.get<0>().end(); }
public:
Container _container;
};
Which gives me the following error from g++.
In member function 'typename boost::multi_index::multi_index_container<OT, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<OT, KT, KM>, KC, mpl_::na>, boost::multi_index::ordered_unique<boost::multi_index::identity<Value>, CMP, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<_CharT> >::nth_index<0>::type::const_iterator OrderBook<OT, KT, KM, KC, CMP>::begin0() const':
error: expected primary-expression before ')' token
In member function 'typename boost::multi_index::multi_index_container<OT, boost::multi_index::indexed_by<boost::multi_index::ordered_unique<boost::multi_index::const_mem_fun<OT, KT, KM>, KC, mpl_::na>, boost::multi_index::ordered_unique<boost::multi_index::identity<Value>, CMP, mpl_::na>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, std::allocator<_CharT> >::nth_index<0>::type::const_iterator OrderBook<OT, KT, KM, KC, CMP>::end0() const':
error: expected primary-expression before ')' token
Sorry for the long error messages, I did consider cleaning them up but I thought I'd better leave them intact in case I removed something crucial.
I tried this...
typedef typename Container::template boost::multi_index::nth_index< 0 >::type index_0;
typedef typename Container::template boost::multi_index::nth_index< 1 >::type index_1;
and it just made g++ even madder :(
Any ideas?
Prefix get<0>() with template:
const_iterator_0 begin0() const { return _container.template get<0>().begin(); }
const_iterator_0 end0 () const { return _container.template get<0>().end(); }
Similar to typename for dependent types, dependent templates have to be prefixed by template:
struct X {
template<class T> void f();
};
template<class T>
void test() {
T::f<int>(); // ill-formed
T::template f<int>(); // ok
}
// ...
test<X>();
And for the curious, that is §14.2/4:
When the name of a member template
specialization appears after . or ->
in a postfix-expression, or after
nested-name-specifier in a
qualified-id, and the
postfix-expression or qualified-id
explicitly depends on a
template-parameter (14.6.2), the
member template name must be prefixed
by the keyword template. Otherwise the
name is assumed to name a
non-template.
Maybe I can guess that some of these functions are not in the boost::multi_index namespace: indexed_b, ordered_unique, const_mem_fun, or identity