I am trying to create an std::unordered_map with an std::pair as key. As you can imagine, this would require me to explicitly provide a class to generate a hash for a given key, as well as an equality comparator for the keys. Here's my code so far:
#include <unordered_map>
#include <memory>
#include <utility>
template <class T, typename U>
struct PairHash{
size_t operator()(const std::pair<T, U> &key){
return std::hash<T>()(key.first) ^ std::hash<U>()(key.second);
}
};
template <class T, typename U>
struct PairEqual{
bool operator()(const std::pair<T, U> &lhs, const std::pair<T, U> &rhs) const{
return lhs.first == rhs.first && lhs.second == rhs.second;
}
};
struct GraphEdge{
};
int main(){
std::unordered_map<std::pair<int, int>,
std::unique_ptr<GraphEdge>,
PairHash<int, int>,
PairEqual<int, int>> edges;
}
However, this gives me a rather (to my eyes at least) inscrutable compiler error:
In file included from /usr/include/c++/5/bits/hashtable.h:35:0,
from /usr/include/c++/5/unordered_map:47,
from prog.cpp:1:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> >':
/usr/include/c++/5/type_traits:137:12: required from 'struct std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > >'
/usr/include/c++/5/type_traits:148:38: required from 'struct std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
/usr/include/c++/5/bits/unordered_map.h:100:66: required from 'class std::unordered_map<std::pair<int, int>, std::unique_ptr<GraphEdge>, PairHash<int, int>, PairEqual<int, int> >'
prog.cpp:29:43: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to '(const PairHash<int, int>) (const std::pair<int, int>&)'
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
prog.cpp:7:12: note: candidate: size_t PairHash<T, U>::operator()(const std::pair<_T1, _T2>&) [with T = int; U = int; size_t = unsigned int] <near match>
size_t operator()(const std::pair<T, U> &key){
^
prog.cpp:7:12: note: passing 'const PairHash<int, int>*' as 'this' argument discards qualifiers
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/unordered_map:38,
from prog.cpp:1:
/usr/include/c++/5/type_traits: In instantiation of 'struct std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >':
/usr/include/c++/5/bits/unordered_map.h:100:66: required from 'class std::unordered_map<std::pair<int, int>, std::unique_ptr<GraphEdge>, PairHash<int, int>, PairEqual<int, int> >'
prog.cpp:29:43: required from here
/usr/include/c++/5/type_traits:148:38: error: 'value' is not a member of 'std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > >'
: public integral_constant<bool, !_Pp::value>
^
In file included from /usr/include/c++/5/unordered_map:48:0,
from prog.cpp:1:
/usr/include/c++/5/bits/unordered_map.h: In instantiation of 'class std::unordered_map<std::pair<int, int>, std::unique_ptr<GraphEdge>, PairHash<int, int>, PairEqual<int, int> >':
prog.cpp:29:43: required from here
/usr/include/c++/5/bits/unordered_map.h:100:66: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
^
/usr/include/c++/5/bits/unordered_map.h:107:45: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::key_type key_type;
^
/usr/include/c++/5/bits/unordered_map.h:108:47: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::value_type value_type;
^
/usr/include/c++/5/bits/unordered_map.h:109:48: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::mapped_type mapped_type;
^
/usr/include/c++/5/bits/unordered_map.h:110:43: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::hasher hasher;
^
/usr/include/c++/5/bits/unordered_map.h:111:46: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::key_equal key_equal;
^
/usr/include/c++/5/bits/unordered_map.h:112:51: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::allocator_type allocator_type;
^
/usr/include/c++/5/bits/unordered_map.h:117:45: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::pointer pointer;
^
/usr/include/c++/5/bits/unordered_map.h:118:50: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::const_pointer const_pointer;
^
/usr/include/c++/5/bits/unordered_map.h:119:47: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::reference reference;
^
/usr/include/c++/5/bits/unordered_map.h:120:52: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::const_reference const_reference;
^
/usr/include/c++/5/bits/unordered_map.h:121:46: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::iterator iterator;
^
/usr/include/c++/5/bits/unordered_map.h:122:51: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::const_iterator const_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:123:51: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::local_iterator local_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:124:57: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::const_local_iterator const_local_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:125:47: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::size_type size_type;
^
/usr/include/c++/5/bits/unordered_map.h:126:52: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
typedef typename _Hashtable::difference_type difference_type;
^
/usr/include/c++/5/bits/unordered_map.h:280:7: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
operator=(initializer_list<value_type> __l)
^
/usr/include/c++/5/bits/unordered_map.h:379:2: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
emplace(_Args&&... __args)
^
/usr/include/c++/5/bits/unordered_map.h:432:7: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
insert(const value_type& __x)
^
/usr/include/c++/5/bits/unordered_map.h:439:2: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
insert(_Pair&& __x)
^
/usr/include/c++/5/bits/unordered_map.h:499:7: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
insert(initializer_list<value_type> __l)
^
/usr/include/c++/5/bits/unordered_map.h:645:7: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
equal_range(const key_type& __x)
^
/usr/include/c++/5/bits/unordered_map.h:649:7: error: 'value' is not a member of 'std::__not_<std::__and_<std::__is_fast_hash<PairHash<int, int> >, std::__detail::__is_noexcept_hash<std::pair<int, int>, PairHash<int, int> > > >'
equal_range(const key_type& __x) const
^
What am I doing wrong?
Apparently, libstdc++ refers to your hash object via const PairHash<int, int>*. Thus calling the operator () which is not marked const in your program is a compiler error.
You can get your code to compile with libstdc++ by making operator() const.
As of 17.6.3.4 (Hash Requirements), a Hash type must provide a size_t operator(KeyType) const;, so your code is indeed incorrect.
You need to make the operator() a const method in your custom functors.
Related
I keep on getting issues when i try to compile this code. I think the origin of the problem is the declaration of the iterator in the set and so the erase operations are giving problems as a consequence.
The compilation error is the following:
the compiler gives this message:
Treecode.cc: In member function ‘void Treecode::recalcular_treecode()’:
Treecode.cc:35:24: error: no match for ‘operator=’ (operand types are ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >}’ and ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >}’)
it = cjt_arb.begin();
^
In file included from /usr/include/c++/7/debug/set.h:34:0,
from /usr/include/c++/7/debug/set:35,
from /usr/include/c++/7/set:66,
from Treecode.hh:10,
from Treecode.cc:1:
/usr/include/c++/7/debug/safe_iterator.h:199:7: note: candidate: __gnu_debug::_Safe_iterator<_Iterator, _Sequence>& __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::operator=(const __gnu_debug::_Safe_iterator<_Iterator, _Sequence>&) [with _Iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; _Sequence = std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
operator=(const _Safe_iterator& __x) _GLIBCXX_NOEXCEPT
^~~~~~~~
/usr/include/c++/7/debug/safe_iterator.h:199:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >}’ to ‘const __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >&’
/usr/include/c++/7/debug/safe_iterator.h:231:7: note: candidate: __gnu_debug::_Safe_iterator<_Iterator, _Sequence>& __gnu_debug::_Safe_iterator<_Iterator, _Sequence>::operator=(__gnu_debug::_Safe_iterator<_Iterator, _Sequence>&&) [with _Iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; _Sequence = std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
operator=(_Safe_iterator&& __x) noexcept
^~~~~~~~
/usr/include/c++/7/debug/safe_iterator.h:231:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >}’ to ‘__gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >&&’
Treecode.cc:42:30: error: no matching function for call to ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::erase(std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator&)’
it = cjt_arb.erase(it);
^
In file included from /usr/include/c++/7/debug/set:35:0,
from /usr/include/c++/7/set:66,
from Treecode.hh:10,
from Treecode.cc:1:
/usr/include/c++/7/debug/set.h:346:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::iterator std::__debug::set<_Key, _Compare, _Allocator>::erase(std::__debug::set<_Key, _Compare, _Allocator>::const_iterator) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::const_iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
erase(const_iterator __position)
^~~~~
/usr/include/c++/7/debug/set.h:346:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >}’ to ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >}’
/usr/include/c++/7/debug/set.h:363:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::size_type std::__debug::set<_Key, _Compare, _Allocator>::erase(const key_type&) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::size_type = long unsigned int; std::__debug::set<_Key, _Compare, _Allocator>::key_type = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >]
erase(const key_type& __x)
^~~~~
/usr/include/c++/7/debug/set.h:363:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >}’ to ‘const key_type& {aka const BinTree<std::pair<std::__cxx11::basic_string<char>, int> >&}’
/usr/include/c++/7/debug/set.h:378:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::iterator std::__debug::set<_Key, _Compare, _Allocator>::erase(std::__debug::set<_Key, _Compare, _Allocator>::const_iterator, std::__debug::set<_Key, _Compare, _Allocator>::const_iterator) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::const_iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
erase(const_iterator __first, const_iterator __last)
^~~~~
/usr/include/c++/7/debug/set.h:378:7: note: candidate expects 2 arguments, 1 provided
Treecode.cc:45:30: error: no matching function for call to ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::erase(std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator&)’
it = cjt_arb.erase(it);
^
In file included from /usr/include/c++/7/debug/set:35:0,
from /usr/include/c++/7/set:66,
from Treecode.hh:10,
from Treecode.cc:1:
/usr/include/c++/7/debug/set.h:346:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::iterator std::__debug::set<_Key, _Compare, _Allocator>::erase(std::__debug::set<_Key, _Compare, _Allocator>::const_iterator) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::const_iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
erase(const_iterator __position)
^~~~~
/usr/include/c++/7/debug/set.h:346:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >}’ to ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena>::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >}’
/usr/include/c++/7/debug/set.h:363:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::size_type std::__debug::set<_Key, _Compare, _Allocator>::erase(const key_type&) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::size_type = long unsigned int; std::__debug::set<_Key, _Compare, _Allocator>::key_type = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >]
erase(const key_type& __x)
^~~~~
/usr/include/c++/7/debug/set.h:363:7: note: no known conversion for argument 1 from ‘std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > > >}’ to ‘const key_type& {aka const BinTree<std::pair<std::__cxx11::basic_string<char>, int> >&}’
/usr/include/c++/7/debug/set.h:378:7: note: candidate: std::__debug::set<_Key, _Compare, _Allocator>::iterator std::__debug::set<_Key, _Compare, _Allocator>::erase(std::__debug::set<_Key, _Compare, _Allocator>::const_iterator, std::__debug::set<_Key, _Compare, _Allocator>::const_iterator) [with _Key = BinTree<std::pair<std::__cxx11::basic_string<char>, int> >; _Compare = Treecode::ordena; _Allocator = std::allocator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >; std::__debug::set<_Key, _Compare, _Allocator>::const_iterator = __gnu_debug::_Safe_iterator<std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >, std::__debug::set<BinTree<std::pair<std::__cxx11::basic_string<char>, int> >, Treecode::ordena> >; typename std::__cxx1998::set<_Key, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<BinTree<std::pair<std::__cxx11::basic_string<char>, int> > >]
erase(const_iterator __first, const_iterator __last)
^~~~~
/usr/include/c++/7/debug/set.h:378:7: note: candidate expects 2 arguments, 1 provided
I've tried dereferencing the declaration doing it = cjt_arb.begin() in the next line but it doesn't work.
#include "Treecode.hh"
using namespace std;
void Treecode::recalcular_treecode() {
set<BinTree<pair<string,int>>>::iterator it = cjt_arb.begin(); // Problem probably here
if (cjt_arb.size() == 1) {tree = *it;}
else {
pair <string, int> a;
pair <string, int> b;
BinTree <pair <string,int> > left = *it;
a = left.value();
it = cjt_arb.erase(it);
BinTree <pair <string,int> > right = *it;
b = right.value();
it = cjt_arb.erase(it);
pair <string, int> node;
if (a.first <b.first) {node.first = a.first + b.first;}
else {node.first = b.first + a.first;}
node.second = a.second + b.second;
BinTree<pair<string,int>> unio(node,left, right);
cjt_arb.insert(unio);
recalcular_treecode();
}
}
As you have already figured out, the compiler is complaining about it = cjt_arb.begin(); not compiling. It tries to tell you why:
error: no match for ‘operator=’ (operand types are ‘std::__debug::set, int> > >::const_iterator {aka __gnu_debug::_Safe_iterator, int> > >, std::__debug::set, int> > > >}’ and ‘std::__debug::set, int> >, Treecode::ordena>::iterator {aka __gnu_debug::_Safe_iterator, int> > >, std::__debug::set, int> >, Treecode::ordena> >}’)
it = cjt_arb.begin();
What it is trying to say is
Error: No valid operator= to assign a set<BinTree<pair<string,int>>>::const_iterator to a set<BinTree<pair<string,int>>>::iterator because that would drop the constness.
Your cjt_arb seems to be const, so you can't modify it, so you cannot get a non-const iterator to it. Replace set<BinTree<pair<string,int>>>::iterator with set<BinTree<pair<string,int>>>::const_iterator or remove the const from cjt_arb and it should compile.
When I declare a variable of std::unordered_map<boost::any, boost::any> type, it throws annoying compile errors.
For an example, any.cc:
#include <map>
#include <boost/any.hpp>
int main() {
std::map<boost::any, boost::any> dict;
return 0;
}
Compiling above code as g++ any.cc -std=c++11 -I/usr/include/boost occurs a lot of errors like following:
In file included from /usr/include/c++/5/bits/hashtable.h:35:0,
from /usr/include/c++/5/unordered_map:47,
from any.cc:1:
/usr/include/c++/5/bits/hashtable_policy.h: In instantiation of ‘struct std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> >’:
/usr/include/c++/5/type_traits:137:12: required from ‘struct std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > >’
/usr/include/c++/5/type_traits:148:38: required from ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
/usr/include/c++/5/bits/unordered_map.h:100:66: required from ‘class std::unordered_map<boost::any, boost::any>’
any.cc:5:48: required from here
/usr/include/c++/5/bits/hashtable_policy.h:85:34: error: no match for call to ‘(const std::hash<boost::any>) (const boost::any&)’
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/include/c++/5/bits/move.h:57:0,
from /usr/include/c++/5/bits/stl_pair.h:59,
from /usr/include/c++/5/utility:70,
from /usr/include/c++/5/unordered_map:38,
from any.cc:1:
/usr/include/c++/5/type_traits: In instantiation of ‘struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’:
/usr/include/c++/5/bits/unordered_map.h:100:66: required from ‘class std::unordered_map<boost::any, boost::any>’
any.cc:5:48: required from here
/usr/include/c++/5/type_traits:148:38: error: ‘value’ is not a member of ‘std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > >’
: public integral_constant<bool, !_Pp::value>
^
In file included from /usr/include/c++/5/unordered_map:48:0,
from any.cc:1:
/usr/include/c++/5/bits/unordered_map.h: In instantiation of ‘class std::unordered_map<boost::any, boost::any>’:
any.cc:5:48: required from here
/usr/include/c++/5/bits/unordered_map.h:100:66: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable;
^
/usr/include/c++/5/bits/unordered_map.h:107:45: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::key_type key_type;
^
/usr/include/c++/5/bits/unordered_map.h:108:47: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::value_type value_type;
^
/usr/include/c++/5/bits/unordered_map.h:109:48: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::mapped_type mapped_type;
^
/usr/include/c++/5/bits/unordered_map.h:110:43: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::hasher hasher;
^
/usr/include/c++/5/bits/unordered_map.h:111:46: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::key_equal key_equal;
^
/usr/include/c++/5/bits/unordered_map.h:112:51: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::allocator_type allocator_type;
^
/usr/include/c++/5/bits/unordered_map.h:117:45: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::pointer pointer;
^
/usr/include/c++/5/bits/unordered_map.h:118:50: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::const_pointer const_pointer;
^
/usr/include/c++/5/bits/unordered_map.h:119:47: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::reference reference;
^
/usr/include/c++/5/bits/unordered_map.h:120:52: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::const_reference const_reference;
^
/usr/include/c++/5/bits/unordered_map.h:121:46: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::iterator iterator;
^
/usr/include/c++/5/bits/unordered_map.h:122:51: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::const_iterator const_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:123:51: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::local_iterator local_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:124:57: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::const_local_iterator const_local_iterator;
^
/usr/include/c++/5/bits/unordered_map.h:125:47: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::size_type size_type;
^
/usr/include/c++/5/bits/unordered_map.h:126:52: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
typedef typename _Hashtable::difference_type difference_type;
^
/usr/include/c++/5/bits/unordered_map.h:280:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
operator=(initializer_list<value_type> __l)
^
/usr/include/c++/5/bits/unordered_map.h:379:2: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
emplace(_Args&&... __args)
^
/usr/include/c++/5/bits/unordered_map.h:432:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
insert(const value_type& __x)
^
/usr/include/c++/5/bits/unordered_map.h:439:2: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
insert(_Pair&& __x)
^
/usr/include/c++/5/bits/unordered_map.h:499:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
insert(initializer_list<value_type> __l)
^
/usr/include/c++/5/bits/unordered_map.h:645:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
equal_range(const key_type& __x)
^
/usr/include/c++/5/bits/unordered_map.h:649:7: error: ‘value’ is not a member of ‘std::__not_<std::__and_<std::__is_fast_hash<std::hash<boost::any> >, std::__detail::__is_noexcept_hash<boost::any, std::hash<boost::any> > > >’
equal_range(const key_type& __x) const
^
But when I use boost::unordered_map rather than std, it works without any errors.
Why?
std::unordered_map uses std::hash as default hasher. There is no specialization of std::hash for boost::any. Because STanDard library does not know anything about entity from 3rd party library.
boost::unordered_map uses boost::hash as default hasher, which has specialization for types from boost library.
Solution: explicitely tell std::unordered_map to use boost::hash<boost::any> as hasher.
When you declare an unordered_map<Key, Value>, you need a hashing function. The default hashing function is const hash<Key>(const Key&).
boost::any, it appears, has such hashing template specialization, but for boost::hash.
So in effect the compiler tries to find a specialization for std::hash for boost::any, but finds only boost::hash specialization.
Consider this:
#include <iostream>
#include <map>
#include <string>
#include <boost/assign/list_of.hpp>
using boost::assign::map_list_of;
const std::map<int, std::map<int, char> > test = map_list_of
(100, map_list_of
(1, 'a')
(2, 'b')
)
(101, map_list_of
(1, 'c')
(2, 'd')
)
;
int main()
{
std::cout << test.find(101)->second.find(2)->second << "\n";
}
I wanted the result to be a program that, when executed, outputs d.
Instead, I get this:
$ clang++ -std=c++03 -O2 -Wall -pedantic -pthread main.cpp
In file included from main.cpp:1:
In file included from /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/iostream:39:
In file included from /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/ostream:38:
In file included from /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/ios:40:
In file included from /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/char_traits.h:39:
In file included from /usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_algobase.h:64:
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_pair.h:119:22: error: call to constructor of 'std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > >' is ambiguous
: first(__p.first), second(__p.second) { }
^ ~~~~~~~~~~
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_tree.h:1843:29: note: in instantiation of function template specialization 'std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > >::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > >' requested here
_M_insert_unique_(end(), *__first);
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_map.h:255:16: note: in instantiation of function template specialization 'std::_Rb_tree<int, std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > >, std::_Select1st<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > >, std::less<int>, std::allocator<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > > >::_M_insert_unique<std::_Deque_iterator<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > >, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > &, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > *> >' requested here
{ _M_t._M_insert_unique(__first, __last); }
^
/usr/local/include/boost/assign/list_of.hpp:163:20: note: in instantiation of function template specialization 'std::map<int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > >, std::less<int>, std::allocator<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > > >::map<std::_Deque_iterator<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > >, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > &, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > *> >' requested here
return Container( begin(), end() );
^
/usr/local/include/boost/assign/list_of.hpp:142:20: note: in instantiation of function template specialization 'boost::assign_detail::converter<boost::assign_detail::generic_list<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > >, std::_Deque_iterator<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > >, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > &, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > *> >::convert<std::map<int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > >, std::less<int>, std::allocator<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > > > >' requested here
return convert<Container>( c, tag_type() );
^
/usr/local/include/boost/assign/list_of.hpp:436:49: note: in instantiation of function template specialization 'boost::assign_detail::converter<boost::assign_detail::generic_list<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > >, std::_Deque_iterator<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > >, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > &, std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > *> >::convert_to_container<std::map<int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > >, std::less<int>, std::allocator<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > > > >' requested here
return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();
^
main.cpp:7:50: note: in instantiation of function template specialization 'boost::assign_detail::generic_list<std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> > > >::operator map<std::map<int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > >, std::less<int>, std::allocator<std::pair<const int, std::map<int, char, std::less<int>, std::allocator<std::pair<const int, char> > > > > > >' requested here
const std::map<int, std::map<int, char> > test = map_list_of
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_map.h:171:7: note: candidate constructor
map(const _Compare& __comp,
^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.9.2/../../../../include/c++/4.9.2/bits/stl_map.h:182:7: note: candidate constructor
map(const map& __x)
^
1 error generated.
(similar results under GCC)
How can I resolve this?
I get a similar error even if I use std::map<int, char>(map_list_of(...)) instead of map_list_of(...) for those inner maps.
C++03 defines two constructors for map that can be called with one argument [lib.map]p2:
explicit map(const Compare& comp = Compare(),
const Allocator& = Allocator());
// [...]
map(const map<Key,T,Compare,Allocator>& x);
boost's map_list_of creates an object of a generic_list class template instantiation, from the recent SVN:
template< class Key, class T >
inline assign_detail::generic_list< std::pair
<
BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<Key>::type,
BOOST_DEDUCED_TYPENAME assign_detail::assign_decay<T>::type
> >
map_list_of( const Key& k, const T& t )
Where the primary generic_list template contains the following conversion operator:
template< class Container >
operator Container() const
{
return this-> BOOST_NESTED_TEMPLATE convert_to_container<Container>();
}
Both map constructors are viable, as this operator allows conversion to both map and Compare. As far as I know, you cannot SFINAE-constrain a conversion operator in C++03.
The map is constructed explicitly when inserting a new node in the outer map. A pair of iterators is used to iterate over the inner generic_list to construct the outer map. Dereferencing this iterator yields a std::pair<int, boost::assign_detail::generic_list<std::pair<int, char> >. The node (value) type of the outer map is std::pair<int const, std::map<int, char> >.
Therefore, the compiler tries to construct the latter type from the former. In C++03, this pair constructor is not SFINAE-constrained, since that's not possible in C++03. [lib.pairs]p1
template<class U, class V> pair(const pair<U, V> &p);
libstdc++ implements this as follows:
template<class _U1, class _U2>
pair(const pair<_U1, _U2>& __p)
: first(__p.first), second(__p.second) { }
I'm not entirely sure if that's compliant, since [lib.pairs]p4
Effects: Initializes members from the corresponding members of the argument, performing implicit conversions as needed.
(But, as I said, SFINAE on ctors cannot be implemented in C++03.)
In C++11 and 14, this also fails, but for a different reason. Here, the pair constructors are SFINAE-constrained. But the constrain requires implicit convertibility (is_convertible), while the program has UB if the target pair of types cannot be constructed from the sources (is_constructible). I've written a bit more about this issue in another SO answer. Interestingly, a proposed solution N4387 to the issue mentioned in that other question says:
It should be noted here, that for the general case the
std::is_constructible<T, U>::value requirement for the non-explicit
constructor which is constrained on std::is_convertible<U, T>::value
is not redundant, because it is possible to create types that can be
copy-initialized but not direct-initialized
This is exactly the case we run into here: A map can be copy-initialized from a generic_list, since this makes the explicit constructor non-viable. But a map cannot be direct-initialized from generic_list, since this makes the conversion ambiguous.
As far as I can see, N4387 does not solve the problem in the OP. On the other hand, with uniform initialization, we have an alternative to map_list_of. And we can SFINAE-constrain conversion operators since C++11.
One solution is to eliminate the explicit constructor by only allowing implicit conversions:
template<typename T> T implicit_cast(T t) { return t; }
implicit_cast<InnerMap>( map_list_of(1, 'a')(2, 'b') )
But there's a more direct way: simply use the convert_to_container member function of generic_list's base class converter (also a class template):
map_list_of(1, 'a')(2, 'b').convert_to_container<InnerMap>()
#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.
This is a simplified version of some code I wrote:
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/fusion/include/filter_if.hpp>
#include <boost/fusion/include/for_each.hpp>
#include <boost/fusion/include/map.hpp>
#include <boost/fusion/include/pair.hpp>
#include <boost/fusion/include/io.hpp>
namespace ids{
struct a0{};
struct a1{};
struct a2{};
struct a3{};
};
typedef boost::fusion::map< boost::fusion::pair<ids::a0,int>
, boost::fusion::pair<ids::a1,double>
, boost::fusion::pair<ids::a2,char>
, boost::fusion::pair<ids::a3,long> > map_type;
typedef boost::mpl::vector<ids::a0,ids::a3> vec_ids_type;
template <typename T>
struct get_first
{
typedef typename T::first_type type;
};
typedef boost::fusion::result_of::filter_if<
map_type
, boost::mpl::contains<
vec_ids_type
, get_first<
boost::mpl::placeholders::_1
>
>
>::type view_type;
struct SetToZero
{
template <typename Field>
void operator()(Field & field) const
{
field.second = 0;
}
};
int main() {
map_type m( boost::fusion::make_pair<ids::a0>(1)
, boost::fusion::make_pair<ids::a1>(2.0)
, boost::fusion::make_pair<ids::a2>('a')
, boost::fusion::make_pair<ids::a3>(4)
);
std::cout << m << std::endl;
view_type v(m);
std::cout << v << std::endl;
boost::fusion::for_each(v,SetToZero());
std::cout << m << std::endl;
}
I want to use view_type to set to zero some elements in an instance of map_type. If the key of one element in map_type is in vec_ids_type, then the data corresponding to that element has to be set to zero, which is done by calling the functor SetToZero. For all this to work, T is meant to be a fusion::pair when get_first<T> is instantiated.
This code compiles and runs perfectly using boost 1.40 and g++ 4.4.3. However I tried to recompile my code using newer versions of boost and g++ and I get compilation errors. Although I think it has to do with boost and not with the compiler, I'll also mention the g++ version. First I tried using boost 1.48.0.2 and g++ 4.6.3, then I tried using boost 1.49.0.1 and g++ 4.7.2. Both attempts failed, giving very similar (if not the same) compilation errors. The error messages are:
tests.cpp: In instantiation of ‘struct get_first<ids::a0>’:
/usr/include/boost/mpl/aux_/has_type.hpp:20:1: required from ‘struct boost::mpl::aux::has_type<get_first<ids::a0>, mpl_::bool_<true> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/quote.hpp:32:36: required from ‘struct boost::mpl::quote1<get_first, mpl_::void_>::apply<ids::a0>’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:36:8: required from ‘struct boost::mpl::apply_wrap1<boost::mpl::quote1<get_first, mpl_::void_>, ids::a0>’
/usr/include/boost/mpl/aux_/preprocessed/gcc/bind.hpp:144:21: [ skipping 16 instantiation contexts ]
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135: required from ‘struct boost::mpl::aux::iter_fold_if_impl<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, mpl_::na, boost::mpl::always<mpl_::bool_<false> > >’
/usr/include/boost/mpl/iter_fold_if.hpp:81:12: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>::result_’
/usr/include/boost/mpl/iter_fold_if.hpp:104:11: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17: required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8: required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54: required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8: required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16: required from here
tests.cpp:37:34: error: no type named ‘first_type’ in ‘struct ids::a0’
In file included from /usr/include/boost/mpl/assert.hpp:17:0,
from /usr/include/boost/mpl/aux_/na_assert.hpp:23,
from /usr/include/boost/mpl/arg.hpp:25,
from /usr/include/boost/mpl/placeholders.hpp:24,
from /usr/include/boost/mpl/apply.hpp:24,
from /usr/include/boost/mpl/aux_/iter_apply.hpp:17,
from /usr/include/boost/mpl/aux_/find_if_pred.hpp:14,
from /usr/include/boost/mpl/find_if.hpp:17,
from /usr/include/boost/mpl/find.hpp:17,
from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
from /usr/include/boost/mpl/contains.hpp:20,
from tests.cpp:12:
/usr/include/boost/mpl/not.hpp: In instantiation of ‘struct boost::mpl::not_<boost::mpl::aux::iter_apply1<boost::mpl::same_as<get_first<mpl_::arg<1> > >, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’:
/usr/include/boost/mpl/aux_/nested_type_wknd.hpp:26:31: required from ‘struct boost::mpl::aux::nested_type_wknd<boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8: required from ‘struct boost::mpl::aux::and_impl<true, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8: required from ‘struct boost::mpl::and_<boost::mpl::not_<boost::is_same<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> > >, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/iter_fold_if.hpp:40:58: required from ‘struct boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >::apply<void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:46:8: required from ‘struct boost::mpl::apply_wrap2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8: [ skipping 4 instantiation contexts ]
/usr/include/boost/mpl/iter_fold_if.hpp:104:11: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17: required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8: required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54: required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8: required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16: required from here
/usr/include/boost/mpl/not.hpp:39:8: error: ‘value’ is not a member of ‘boost::mpl::aux::nested_type_wknd<boost::mpl::aux::iter_apply1<boost::mpl::same_as<get_first<mpl_::arg<1> > >, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
In file included from /usr/include/boost/mpl/aux_/include_preprocessed.hpp:37:0,
from /usr/include/boost/mpl/and.hpp:42,
from /usr/include/boost/mpl/logical.hpp:18,
from /usr/include/boost/mpl/iter_fold_if.hpp:19,
from /usr/include/boost/mpl/find_if.hpp:19,
from /usr/include/boost/mpl/find.hpp:17,
from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
from /usr/include/boost/mpl/contains.hpp:20,
from tests.cpp:12:
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp: In instantiation of ‘struct boost::mpl::aux::and_impl<true, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’:
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:48:8: required from ‘struct boost::mpl::and_<boost::mpl::not_<boost::is_same<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> > >, boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >’
/usr/include/boost/mpl/iter_fold_if.hpp:40:58: required from ‘struct boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >::apply<void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply_wrap.hpp:46:8: required from ‘struct boost::mpl::apply_wrap2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/apply.hpp:67:8: required from ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:62:63: required from ‘struct boost::mpl::aux::iter_fold_if_forward_step<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135: [ skipping 2 instantiation contexts ]
/usr/include/boost/mpl/iter_fold_if.hpp:104:11: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17: required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8: required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54: required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8: required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16: required from here
/usr/include/boost/mpl/aux_/preprocessed/gcc/and.hpp:23:8: error: ‘value’ is not a member of ‘boost::mpl::aux::nested_type_wknd<boost::mpl::apply1<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> > >’
In file included from /usr/include/boost/mpl/aux_/include_preprocessed.hpp:37:0,
from /usr/include/boost/mpl/aux_/iter_fold_if_impl.hpp:32,
from /usr/include/boost/mpl/iter_fold_if.hpp:25,
from /usr/include/boost/mpl/find_if.hpp:19,
from /usr/include/boost/mpl/find.hpp:17,
from /usr/include/boost/mpl/aux_/contains_impl.hpp:20,
from /usr/include/boost/mpl/contains.hpp:20,
from tests.cpp:12:
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp: In instantiation of ‘struct boost::mpl::aux::iter_fold_if_forward_step<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0> >’:
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:101:135: required from ‘struct boost::mpl::aux::iter_fold_if_impl<boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, mpl_::na, boost::mpl::always<mpl_::bool_<false> > >’
/usr/include/boost/mpl/iter_fold_if.hpp:81:12: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>::result_’
/usr/include/boost/mpl/iter_fold_if.hpp:104:11: required from ‘struct boost::mpl::iter_fold_if<boost::mpl::vector<ids::a0, ids::a3>, void, mpl_::arg<1>, boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, mpl_::na, mpl_::na>’
/usr/include/boost/mpl/find_if.hpp:39:17: required from ‘struct boost::mpl::find_if<boost::mpl::vector<ids::a0, ids::a3>, boost::mpl::same_as<get_first<mpl_::arg<1> > > >’
/usr/include/boost/mpl/find.hpp:28:8: required from ‘struct boost::mpl::find<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/aux_/contains_impl.hpp:33:54: required from ‘struct boost::mpl::contains_impl<boost::mpl::aux::vector_tag>::apply<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
/usr/include/boost/mpl/contains.hpp:30:8: required from ‘struct boost::mpl::contains<boost::mpl::vector<ids::a0, ids::a3>, get_first<mpl_::arg<1> > >’
tests.cpp:70:16: required from here
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:62:63: error: no type named ‘type’ in ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
/usr/include/boost/mpl/aux_/preprocessed/gcc/iter_fold_if_impl.hpp:65:78: error: no type named ‘type’ in ‘struct boost::mpl::apply2<boost::mpl::protect<boost::mpl::aux::iter_fold_if_pred<boost::mpl::protect<boost::mpl::aux::find_if_pred<boost::mpl::same_as<get_first<mpl_::arg<1> > > >, 0>, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 2l> >, 0>, void, boost::mpl::v_iter<boost::mpl::vector<ids::a0, ids::a3>, 0l> >’
tests.cpp: In instantiation of ‘struct get_first<mpl_::arg<1> >’:
tests.cpp:70:16: required from here
tests.cpp:37:34: error: no type named ‘first_type’ in ‘struct mpl_::arg<1>’
From the very first line of the error messages there is something completely unexpected for me tests.cpp: In instantiation of ‘struct get_first<ids::a0>’. This should not happen because get_first should only be instantiated using elements of map_type, i.e. fusion::pair. I really don't understand why this is happening.
As I said, it works perfectly with boost 1.40, and it makes a lot of sense for me as it is written now, so I really don't see where the error is. My only guess is that something might have changed in the newer versions of fusion or mpl that is causing this. Actually I checked the change logs of Boost.Fusion and Boost and something related to fusion views have been modified/added. Maybe a bug? or, Am I missing something? why it does not work with the newer versions of boost that I tried?
thanks in advance!
Using:
typedef boost::fusion::result_of::filter_if<
map_type
,
boost::mpl::lambda<
boost::mpl::contains<
vec_ids_type
,
get_first<
boost::mpl::_1
>
>
>::type
>::type view_type;
Seems to make it work as you can see here. Currently LiveWorkspace uses boost 1.53.0.