作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个类模板 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/
我有一个带有模板函数的基类,该函数具有通用模板类型和专用版本。 #ifndef BASE_CLASS #define BASE_CLASS #include using namespace std;
我有这个 3D vector 模板 template class Vec3TYPE{ public: union{ struct{ TYPE x,y,z; }; struct{ TY
我是一名优秀的程序员,十分优秀!