0

パラメータをID取るクラス テンプレートがありますT

  • Tkey_type定義されている場合は、型のオブジェクトをID呼び出して、ストレージの識別子を取得します。 get_key()T
  • が定義されTていない場合は、オブジェクトのアドレスを識別子として使用します。key_typeID

この時点まで、コードは正常に機能します。

Composite_Keyここで、可変個引数テンプレート パラメーターを として受け取る新しい可変個引数クラス テンプレートを定義したいと思いますstd::tuple。この新しいコードを で動作させようとしてIDいますが、理解に苦労しているコンパイル エラーの壁が発生しています。

エラーは の欠落を示しているようですがoperator<()、これは で定義されているため奇妙IDです。私は何が間違っているのか途方に暮れています。

テスト コードを含む以下のコードは、最後の行 (コメント) まで正常に動作します。

コード

#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 : a ptr
    static type get_key( T const& t ) { return &t; }
};

template<typename T>
struct ptr_or_key_type<T, typename void_<typename T::key_type>::type> {
    using type = typename T::key_type;   // the specialised key_type
    static type get_key( T const& t ) { return 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;
        return *this;
    }
public:
    bool operator==( ID const& rhs ) const { return m_id==rhs.m_id; }
    bool operator!=( ID const& rhs ) const { return !(*this==rhs);  }
    bool operator<( ID const& rhs ) const  { return m_id<rhs.m_id;  }
    bool operator<=( ID const& rhs ) const { return m_id<=rhs.m_id; }
    bool operator>( ID const& rhs ) const  { return m_id>rhs.m_id;  }
    bool operator>=( ID const& rhs ) const { return 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 { return m_key; }
};

struct Char_Key {
    using key_type = char;

    char m_key;
    Char_Key( char key ) : m_key( key ) { }
    char get_key() const { return m_key; }
};

struct Int_Key {
    using key_type = int;

    int m_key;
    Int_Key( int key ) : m_key( key ) { }
    int get_key() const { return 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 { return m_key; }
};

// -----------------------------------------------------------------------------

int main( int argc, char* argv[] )
{
    // Plain_Class will use address of object as 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 );    // two unique addresses, so two in the set

    // String_Key will use std::string as the key
    String_Key h( "abc" ), i( "abc" );
    std::set<ID<String_Key>>  s2;
    s2.insert( h );
    s2.insert( i );
    assert( s2.size()==1u );   // since sets must have unique values

    // attempt a 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: everything above this line compiles fine
#if 0
    s3.insert( k );
    assert( s3.size()==1u );   // since sets must have unique values
#endif
}

エラーの壁

In file included from 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 from ‘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 from ‘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 from ‘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 from ‘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 from ‘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 from here
/usr/include/c++/4.7/tuple:781:63: error: no match for ‘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 from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::pair<_T1, _T2>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::reverse_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::reverse_iterator<_IteratorL>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::move_iterator<_IteratorL>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::move_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/string:54:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::basic_string<_CharT, _Traits, _Alloc>’
In file included from /usr/include/c++/4.7/string:54:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::basic_string<_CharT, _Traits, _Alloc>’
In file included from /usr/include/c++/4.7/string:54:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   mismatched types ‘const _CharT*’ and ‘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’ is not derived from ‘const std::tuple<_TElements ...>’
In file included from /usr/include/c++/4.7/set:60:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/set:61:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::set<_Key, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/set:62:0,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::multiset<_Key, _Compare, _Alloc>’
/usr/include/c++/4.7/tuple:781:63: error: no match for ‘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 from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::pair<_T1, _T2>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::reverse_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::reverse_iterator<_IteratorL>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from 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 from sandbox.cpp:2:0:
/usr/include/c++/4.7/tuple:781:63: note:   ‘const String_Key’ is not derived from ‘const std::move_iterator<_IteratorL>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/char_traits.h:41,
                 from /usr/include/c++/4.7/string:42,
                 from sandbox.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:1063:5: note: template<class _Iterator> bool 

答え

以下の jmetcalf で示されているように、すべての Key クラスも実装する必要がありますoperator<()operator<()in はID実際にはstd::tuple'soperator<()に依存し、これはすべての個々の型'に依存するため、これは理にかなっていoperator<()ます。

4

1 に答える 1

2

operator<()セットで使用する場合は、主要なクラスに実装する必要があります。std::tuple::operator<()実装では、これがすべてのサブタイプに対して実装されている必要があります (辞書式に左から右に比較します) 。

他の無関係なものからそれを選択すると、エラーはかなり明白です。

/usr/include/c++/4.7/tuple:781:63: エラー: 'std::get< 0 ul, { String_Key , Int_Key, Char_Key}>((* & __uの '<strong>operator<' に一致しません)) < std::get< 0 ul, { String_Key , Int_Key, Char_Key}>((* & __t))'</p>

于 2013-02-13T18:53:22.813 に答える