Sunday, 15 May 2011

c++ - Compile problems: building a Composite_Key variadic template class using tuples -



c++ - Compile problems: building a Composite_Key variadic template class using tuples -

i have id class template takes parameter t.

if t has key_type defined, id calls get_key() on object of type t identifier storage. if t not have key_type defined, id utilize address of object identifier.

the code works fine point.

now, define new variadic class template composite_key takes variadic template parameters std::tuple. trying new code work id, getting wall of compilation errors having hard time understanding.

the errors seem indicate missing operator<(), odd because it's defined in id; i'm @ loss i'm doing wrong.

the code below, including test code, works fine until lastly line (commented).

code

#include <string> #include <tuple> #include <set> #include <cassert> template<typename t> struct void_ { using type = void; }; // ----------------------------------------------------------------------------- template<typename t, typename = void> struct ptr_or_key_type { using type = t const*; // our default key_type : ptr static type get_key( t const& t ) { homecoming &t; } }; template<typename t> struct ptr_or_key_type<t, typename void_<typename t::key_type>::type> { using type = typename t::key_type; // specialised key_type static type get_key( t const& t ) { homecoming t.get_key(); } }; // ----------------------------------------------------------------------------- template<typename t> class id { private: typename ptr_or_key_type<t>::type m_id; public: id( t const& t ) : m_id( ptr_or_key_type<t>::get_key( t )) { } id( id const& rhs ) : m_id( rhs.m_id ) { } ~id() { } id& operator=( id const& rhs ) { if ( &rhs!=this ) m_id = rhs.m_id; homecoming *this; } public: bool operator==( id const& rhs ) const { homecoming m_id==rhs.m_id; } bool operator!=( id const& rhs ) const { homecoming !(*this==rhs); } bool operator<( id const& rhs ) const { homecoming m_id<rhs.m_id; } bool operator<=( id const& rhs ) const { homecoming m_id<=rhs.m_id; } bool operator>( id const& rhs ) const { homecoming m_id>rhs.m_id; } bool operator>=( id const& rhs ) const { homecoming m_id>=rhs.m_id; } }; // ----------------------------------------------------------------------------- struct plain_class { }; struct string_key { using key_type = std::string; std::string m_key; string_key( std::string const& key ) : m_key( key ) { } std::string const& get_key() const { homecoming m_key; } }; struct char_key { using key_type = char; char m_key; char_key( char key ) : m_key( key ) { } char get_key() const { homecoming m_key; } }; struct int_key { using key_type = int; int m_key; int_key( int key ) : m_key( key ) { } int get_key() const { homecoming m_key; } }; template<typename... args> struct composite_key { using key_type = std::tuple<args...>; key_type m_key; composite_key( key_type const& key ) : m_key( key ) { } key_type const& get_key() const { homecoming m_key; } }; // ----------------------------------------------------------------------------- int main( int argc, char* argv[] ) { // plain_class utilize address of object key plain_class f,g; id<plain_class> id_f( f ), id_g( g ); assert( id_f!=id_g ); std::set<id<plain_class>> s; s.insert( f ); s.insert( g ); assert( s.size()==2u ); // 2 unique addresses, 2 in set // string_key utilize std::string key string_key h( "abc" ), i( "abc" ); std::set<id<string_key>> s2; s2.insert( h ); s2.insert( ); assert( s2.size()==1u ); // since sets must have unique values // effort composite key type using my_composite = composite_key<string_key,int_key,char_key>; my_composite j( std::make_tuple( string_key{ "foo" }, int_key{ 1 }, char_key{ 'c' } )), k( std::make_tuple( string_key{ "foo" }, int_key{ 1 }, char_key{ 'c' } )) ; std::set<id<my_composite>> s3; s3.insert( j ); // failure: above line compiles fine #if 0 s3.insert( k ); assert( s3.size()==1u ); // since sets must have unique values #endif }

wall of errors

in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple: in instantiation of ‘static bool std::__tuple_compare<0ul, __i, __j, _tp, _up>::__less(const _tp&, const _up&) [with long unsigned int __i = 0ul; long unsigned int __j = 3ul; _tp = std::tuple<string_key, int_key, char_key>; _up = std::tuple<string_key, int_key, char_key>]’: /usr/include/c++/4.7/tuple:814:62: required ‘bool std::operator<(const std::tuple<_telements ...>&, const std::tuple<_elements ...>&) [with _telements = {string_key, int_key, char_key}; _uelements = {string_key, int_key, char_key}]’ sandbox.cpp:50:59: required ‘bool id<t>::operator<(const id<t>&) const [with t = composite_key<string_key, int_key, char_key>; id<t> = id<composite_key<string_key, int_key, char_key> >]’ /usr/include/c++/4.7/bits/stl_function.h:237:22: required ‘bool std::less<_tp>::operator()(const _tp&, const _tp&) const [with _tp = id<composite_key<string_key, int_key, char_key> >]’ /usr/include/c++/4.7/bits/stl_tree.h:1285:4: required ‘std::pair<std::_rb_tree_iterator<_val>, bool> std::_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>::_m_insert_unique(_arg&&) [with _arg = id<composite_key<string_key, int_key, char_key> >; _key = id<composite_key<string_key, int_key, char_key> >; _val = id<composite_key<string_key, int_key, char_key> >; _keyofvalue = std::_identity<id<composite_key<string_key, int_key, char_key> > >; _compare = std::less<id<composite_key<string_key, int_key, char_key> > >; _alloc = std::allocator<id<composite_key<string_key, int_key, char_key> > >]’ /usr/include/c++/4.7/bits/stl_set.h:424:40: required ‘std::pair<typename std::_rb_tree<_key, _key, std::_identity<_key>, _compare, typename _alloc::rebind<_key>::other>::const_iterator, bool> std::set<_key, _compare, _alloc>::insert(std::set<_key, _compare, _alloc>::value_type&&) [with _key = id<composite_key<string_key, int_key, char_key> >; _compare = std::less<id<composite_key<string_key, int_key, char_key> > >; _alloc = std::allocator<id<composite_key<string_key, int_key, char_key> > >; typename std::_rb_tree<_key, _key, std::_identity<_key>, _compare, typename _alloc::rebind<_key>::other>::const_iterator = std::_rb_tree_const_iterator<id<composite_key<string_key, int_key, char_key> > >; std::set<_key, _compare, _alloc>::value_type = id<composite_key<string_key, int_key, char_key> >]’ sandbox.cpp:121:15: required here /usr/include/c++/4.7/tuple:781:63: error: no match ‘operator<’ in ‘std::get<0ul, {string_key, int_key, char_key}>((* & __u)) < std::get<0ul, {string_key, int_key, char_key}>((* & __t))’ /usr/include/c++/4.7/tuple:781:63: note: candidates are: in file included /usr/include/c++/4.7/bits/stl_algobase.h:65:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_pair.h:212:5: note: template<class _t1, class _t2> constexpr bool std::operator<(const std::pair<_t1, _t2>&, const std::pair<_t1, _t2>&) /usr/include/c++/4.7/bits/stl_pair.h:212:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::pair<_t1, _t2>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:299:5: note: template<class _iterator> bool std::operator<(const std::reverse_iterator<_iterator>&, const std::reverse_iterator<_iterator>&) /usr/include/c++/4.7/bits/stl_iterator.h:299:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::reverse_iterator<_iterator>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:349:5: note: template<class _iteratorl, class _iteratorr> bool std::operator<(const std::reverse_iterator<_iteratorl>&, const std::reverse_iterator<_iteratorr>&) /usr/include/c++/4.7/bits/stl_iterator.h:349:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::reverse_iterator<_iteratorl>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note: template<class _iteratorl, class _iteratorr> bool std::operator<(const std::move_iterator<_iteratorl>&, const std::move_iterator<_iteratorr>&) /usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::move_iterator<_iteratorl>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note: template<class _iterator> bool std::operator<(const std::move_iterator<_iterator>&, const std::move_iterator<_iterator>&) /usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::move_iterator<_iterator>’ in file included /usr/include/c++/4.7/string:54:0, sandbox.cpp:1: /usr/include/c++/4.7/bits/basic_string.h:2566:5: note: template<class _chart, class _traits, class _alloc> bool std::operator<(const std::basic_string<_chart, _traits, _alloc>&, const std::basic_string<_chart, _traits, _alloc>&) /usr/include/c++/4.7/bits/basic_string.h:2566:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::basic_string<_chart, _traits, _alloc>’ in file included /usr/include/c++/4.7/string:54:0, sandbox.cpp:1: /usr/include/c++/4.7/bits/basic_string.h:2578:5: note: template<class _chart, class _traits, class _alloc> bool std::operator<(const std::basic_string<_chart, _traits, _alloc>&, const _chart*) /usr/include/c++/4.7/bits/basic_string.h:2578:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::basic_string<_chart, _traits, _alloc>’ in file included /usr/include/c++/4.7/string:54:0, sandbox.cpp:1: /usr/include/c++/4.7/bits/basic_string.h:2590:5: note: template<class _chart, class _traits, class _alloc> bool std::operator<(const _chart*, const std::basic_string<_chart, _traits, _alloc>&) /usr/include/c++/4.7/bits/basic_string.h:2590:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: mismatched types ‘const _chart*’ , ‘string_key’ /usr/include/c++/4.7/tuple:808:5: note: template<class ... _telements, class ... _uelements> bool std::operator<(const std::tuple<_telements ...>&, const std::tuple<_elements ...>&) /usr/include/c++/4.7/tuple:808:5: note: template argument deduction/substitution failed: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::tuple<_telements ...>’ in file included /usr/include/c++/4.7/set:60:0, sandbox.cpp:3: /usr/include/c++/4.7/bits/stl_tree.h:873:5: note: template<class _key, class _val, class _keyofvalue, class _compare, class _alloc> bool std::operator<(const std::_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>&, const std::_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>&) /usr/include/c++/4.7/bits/stl_tree.h:873:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::_rb_tree<_key, _val, _keyofvalue, _compare, _alloc>’ in file included /usr/include/c++/4.7/set:61:0, sandbox.cpp:3: /usr/include/c++/4.7/bits/stl_set.h:721:5: note: template<class _key, class _compare, class _alloc> bool std::operator<(const std::set<_key, _compare, _alloc>&, const std::set<_key, _compare, _alloc>&) /usr/include/c++/4.7/bits/stl_set.h:721:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::set<_key, _compare, _alloc>’ in file included /usr/include/c++/4.7/set:62:0, sandbox.cpp:3: /usr/include/c++/4.7/bits/stl_multiset.h:702:5: note: template<class _key, class _compare, class _alloc> bool std::operator<(const std::multiset<_key, _compare, _alloc>&, const std::multiset<_key, _compare, _alloc>&) /usr/include/c++/4.7/bits/stl_multiset.h:702:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::multiset<_key, _compare, _alloc>’ /usr/include/c++/4.7/tuple:781:63: error: no match ‘operator<’ in ‘std::get<0ul, {string_key, int_key, char_key}>((* & __t)) < std::get<0ul, {string_key, int_key, char_key}>((* & __u))’ /usr/include/c++/4.7/tuple:781:63: note: candidates are: in file included /usr/include/c++/4.7/bits/stl_algobase.h:65:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_pair.h:212:5: note: template<class _t1, class _t2> constexpr bool std::operator<(const std::pair<_t1, _t2>&, const std::pair<_t1, _t2>&) /usr/include/c++/4.7/bits/stl_pair.h:212:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::pair<_t1, _t2>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:299:5: note: template<class _iterator> bool std::operator<(const std::reverse_iterator<_iterator>&, const std::reverse_iterator<_iterator>&) /usr/include/c++/4.7/bits/stl_iterator.h:299:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::reverse_iterator<_iterator>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:349:5: note: template<class _iteratorl, class _iteratorr> bool std::operator<(const std::reverse_iterator<_iteratorl>&, const std::reverse_iterator<_iteratorr>&) /usr/include/c++/4.7/bits/stl_iterator.h:349:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::reverse_iterator<_iteratorl>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note: template<class _iteratorl, class _iteratorr> bool std::operator<(const std::move_iterator<_iteratorl>&, const std::move_iterator<_iteratorr>&) /usr/include/c++/4.7/bits/stl_iterator.h:1057:5: note: template argument deduction/substitution failed: in file included sandbox.cpp:2:0: /usr/include/c++/4.7/tuple:781:63: note: ‘const string_key’ not derived ‘const std::move_iterator<_iteratorl>’ in file included /usr/include/c++/4.7/bits/stl_algobase.h:68:0, /usr/include/c++/4.7/bits/char_traits.h:41, /usr/include/c++/4.7/string:42, sandbox.cpp:1: /usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note: template<class _iterator> bool

answer

as indicated jmetcalf below, key classes must implement operator<(). makes sense because operator<() in id depends on std::tuple's operator<(), depends on individual types' operator<().

you need implement operator<() in key classes if want utilize them in set. std::tuple::operator<() implementation requires implemented sub-types (it compares lexicographically left right)

the error pretty obvious 1 time pick out of other irrelevant stuff:

/usr/include/c++/4.7/tuple:781:63: error: no match ‘operator<’ in ‘std::get<0 ul, {string_key, int_key, char_key}>((* & __u)) < std::get<0 ul, {string_key, int_key, char_key}>((* & __t))’

c++ c++11 tuples variadic-templates

No comments:

Post a Comment