gpt4 book ai didi

c++ - 如何根据 T::key_type 的定义专门化类模板?

转载 作者:行者123 更新时间:2023-11-30 02:00:50 26 4
gpt4 key购买 nike

我有一个类模板 ID ,目前使用对象的地址作为其标识符。

我想对此类模板进行专门化,这样如果 T有一个 key_type定义,我会调用get_key()在对象上并将其用作标识符。当然,我也会存储那个值,所以和原来的实现会有很高的重叠度。

在最大限度地提高代码重用的同时实现这一目标的最佳方法是什么?

在下面的代码中,我想要 ID<Bar>自动使用std::string在它的胆量而不是Bar const* .

我试着研究 SFINAE,以此来确定是否 T::key_type已定义,但我只能找到函数模板的示例。

代码

#include <string>
#include <set>
#include <cassert>

template<typename T>
class ID
{
private:
T const* m_id;
public:
ID( T const& t ) :
m_id( &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 Foo { };
struct Bar {
using key_type = std::string;

std::string m_key;
Bar( std::string const& key ) : m_key( key ) { }
};

int main( int argc, char* argv[] )
{
Foo f,g;

ID<Foo> id_f( f ), id_g( g );
assert( id_f!=id_g );

std::set<ID<Foo>> s;
s.insert( f );
s.insert( g );

assert( s.size()==2u );

Bar h( "abc" ), i( "abc" );
std::set<ID<Bar>> s2;
s2.insert( h );
s2.insert( i );
assert( s2.size()==1u );
}

我能够根据 Seth Carnegie's answer below 编写解决方案.

解决方案

#include <string>
#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 ) { 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 Foo { };
struct Bar {
using key_type = std::string;

std::string m_key;
Bar( std::string const& key ) : m_key( key ) { }
std::string const& get_key() const { return m_key; }
};

int main( int argc, char* argv[] )
{
Foo f,g;

ID<Foo> id_f( f ), id_g( g );
assert( id_f!=id_g );

std::set<ID<Foo>> s;
s.insert( f );
s.insert( g );

assert( s.size()==2u );

Bar h( "abc" ), i( "abc" );
std::set<ID<Bar>> s2;
s2.insert( h );
s2.insert( i );
assert( s2.size()==1u );
}

最佳答案

您可以使用 SFINAE 特征类的小组合:

template<typename T>
struct void_ {
using type = void;
};

template<typename T, typename = void>
struct key_type_or_id {
using type = T const*; // Our default key_type
};

template<typename T>
struct key_type_or_id<T, typename void_<typename T::key_type>::type> {
using type = typename T::key_type; // The specialised key_type
};

...

template<typename T>
class ID
{
private:
typename key_type_or_id<T>::type m_id;

...

关于c++ - 如何根据 T::key_type 的定义专门化类模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14722576/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com