将一个通用枚举类型作为模板参数 [英] Give a generic enum type as template argument
问题描述
简而言之:
有一种方法,我可以喂一个一般
模板类, 枚举
类型?例如:
模板< typename T> struct General {};
struct EnumSpecific:General< any_enum_type> {};
< int>
b b ul>
Holder
类以通用方式处理任何类型的数据。 Holder
s行为的特定算法。一般
(如 IntSpecific
, DoubleSpecific
, StringSpecific
, MoreSophisticatedTypeSpecific
..)定义如何处理一些具体 Holder
类型。 EnumSpecific
规范?这里是boilt down代码,使我的问题发生:
template< typename T>
class Holder {
public:
Holder(T const& t):_value(t){};
//通用方法
void generics(){};
//有关值的方法:
void set(T const& t / *,setInfo * /){
// ..检查实际变化,通知变化的好友。 。
_value = t;
};
T值(/ * readInfo * /){
// ..取决于如何/为什么值被读取的东西
return _value;
};
private:
T _value;
};
//(在现实中,所有`generics`方法来自一个父类,未经考虑的类)
//一个涉及这样的`Holder`s的泛型过程:
template<类型名T>
class General {
public:
typedef bool / *或anything * / KnownReturnTypes;
General(Holder< T> * const a
,Holder< T> * const b)
:_a(a)
,_b(b)
{ ;
void methods(){
//使用所有`Holder`的
的常见行为_a> generics();
// ..或依赖于实际值的方法:
KnownReturnTypes knr(valuedMethods());
if(knr){} else {}
// ...
};
//使用多态来适应每种情况..
virtual KnownReturnTypes valuedMethods()= 0;
protected:
Holder< T> * _a;
Holder< T> * _b;
};
//整数类型的特殊化示例(可能有其他)
class IntSpecific:General< int> {
public:
IntSpecific(Holder< int> * const a
,Holder< int> * const b)
:General< int>(a,b)
{};
//实现valuedMethods:
virtual KnownReturnTypes valuedMethods(){
return _a-> value()> _b-> value(); // dummy
}
};
//枚举类型的专用化:
// * * * class EnumSpecific:General< any_enum_type> {//不存在* *
类EnumSpecific:General< int> {
public:
EnumSpecific(Holder< int> * const a
,Holder< int> * const b)
:General< int>(a,b)
{};
//只使用枚举类型提供的属性和方法:
virtual KnownReturnTypes valuedMethods(){
return _a-> value()== _b-> value() // dummy
}
};
//一个特殊情况
typedef枚举{一,二,三}枚举;
typedef Holder< Enum>枚举器
int main(){
//检查`IntSpecific`是否正常。
Holder< int> * i(new Holder< int>(3));
Holder< int> * j(new Holder< int>(5));
IntSpecific是(i,j); // 好。
//尝试'EnumSpecific'
EnumHolder * a(new EnumHolder {One});
EnumHolder * b(new EnumHolder {Two});
EnumSpecific es(static_cast< Holder< int> *(a)// invalid cast
,static_cast< Holder< Enum> *>(b) // unexpected type
//这是因为编译器不知道什么
// EnumSpecific实际上是*是*。如何告诉他更多关于它?
return EXIT_SUCCESS;
}
我应该在 EnumSpecific :
我需要使用某种类型的
我们可以使用 href =http://en.cppreference.com/w/cpp/types/enable_if =nofollow> std :: enable_if
和< a href =http://en.cppreference.com/w/cpp/types/is_enum =nofollow> std :: is_enum
。作为示例,这是一个类,它将枚举类型作为模板参数。
#include< type_traits&
枚举枚举{FOO,BAR};
template< typename T,typename std :: enable_if< std :: is_enum< T> :: value> :: type * = nullptr>
class Test {};
int main()
{
Test< Enum>一个; // ok
Test< double> b; // error
}
In short:
Is there a way I can feed a General
templated class with something that only represent an enum
type? Something like:
template <typename T> struct General {};
struct EnumSpecific : General<any_enum_type> {};
<int>
is too much / does not work in my case.
My specific case:
- A templated
Holder
class handles any kind of data in a generic way. - An abstract
General
class implements specific algorithms relying on theHolder
s' behaviour. - Template specifications of
General
(likeIntSpecific
,DoubleSpecific
,StringSpecific
,MoreSophisticatedTypeSpecific
..) define how to deal with some concreteHolder
types. - How can I properly define an
EnumSpecific
specification?
Here is boilt down code making my problem occur:
// A templated value holder:
template <typename T>
class Holder {
public:
Holder(T const& t) : _value(t) {};
// generic methods
void generics() {};
// methods concerning the value:
void set(T const& t /*, setInfo */) {
// .. check for an actual change, notify buddies of the change..
_value = t;
};
T value(/*readInfo*/) {
// .. do stuff depending on how / why the value is read..
return _value;
};
private:
T _value;
};
// (in reality, all `generics` methods come from a parent, untemplated class)
// A generic process involving such `Holder`s:
template <typename T>
class General {
public:
typedef bool /* or anything */ KnownReturnTypes;
General(Holder<T>* const a
, Holder<T>* const b)
: _a(a)
, _b(b)
{};
void methods() {
// Use common behavior of all `Holder`'s
_a->generics();
// .. or methods that rely on the actual values:
KnownReturnTypes knr( valuedMethods() );
if (knr) {} else {}
// ...
};
// Use polymorphism to adapt to each situation..
virtual KnownReturnTypes valuedMethods() = 0;
protected:
Holder<T>* _a;
Holder<T>* _b;
};
// Example of specialization for integral types (there might be others)
class IntSpecific : General<int> {
public:
IntSpecific(Holder<int>* const a
, Holder<int>* const b)
: General<int>(a, b)
{};
// implement the valuedMethods:
virtual KnownReturnTypes valuedMethods() {
return _a->value() > _b->value(); // dummy
}
};
// Specialization for enum types:
// * * * class EnumSpecific : General<any_enum_type> { // does not exist * *
class EnumSpecific : General<int> {
public:
EnumSpecific( Holder<int>* const a
, Holder<int>* const b)
: General<int>(a, b)
{};
// only use properties and methods offered by an enum type:
virtual KnownReturnTypes valuedMethods() {
return _a->value() == _b->value(); // dummy
}
};
// One particular case
typedef enum {One, Two, Three} Enum;
typedef Holder<Enum> EnumHolder;
int main() {
// Check that `IntSpecific` works fine.
Holder<int>* i( new Holder<int>(3) );
Holder<int>* j( new Holder<int>(5) );
IntSpecific is(i, j); // ok.
// Try the `EnumSpecific`
EnumHolder* a( new EnumHolder { One } );
EnumHolder* b( new EnumHolder { Two } );
EnumSpecific es(static_cast<Holder<int>*>(a) // invalid cast
, static_cast<Holder<Enum>*>(b)); // unexpected type
// This is because the compiler doesn't know enough about what
// EnumSpecific actually *is*. How to tell him more about it?
return EXIT_SUCCESS;
}
What should I feed the template argument with in EnumSpecific : General<??>
to make things clear for the compiler?
Do I need to use some kind of enum_type
concept and more sophisticated tools from generic programming?
We can accomplish this with std::enable_if
and std::is_enum
. As a sample this is a class that will take an enum type as a template parameter.
#include <type_traits>
enum Enum { FOO, BAR};
template<typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
class Test {};
int main()
{
Test<Enum> a; // ok
Test<double> b; // error
}
这篇关于将一个通用枚举类型作为模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!