I need to specialize
template< typename T, int Id >
struct ValueTraits
{
// Default version
static int getValue() { return 0; }
};
for any subclass of some ConcreteClass
as T
:
class ConcreteClass {};
struct ConcreteSub1: public ConcreteClass
{
static int get() { return 1; }
};
struct ConcreteSub2: public ConcreteClass
{
static int get() { return 2; }
};
and for some predetermined value of Id
, say 123
,
...so that ValueTraits< ConcreteSub1, 123 >::getValue()
would call ConcreteSub1::get()
and return 1
, and ValueTraits< ConcreteSub2, 123 >::getValue()
would call ConcreteSub2::get()
and return 2
. Use of any Id
other than 123
or the class other than a subclass of ConcreteClass
should fall back to the default version of the template.
Now, I understand that I could use std::enable_if
with std::is_base_of
, but wouldn't that require adding an additional dummy type argument to ValueTraits
? Something like this would work, for example:
#include <stdio.h>
#include <type_traits>
template< typename T, int Id, typename Dummy = void >
struct ValueTraits
{
// Default version
static int getValue() { return 0; }
};
class ConcreteClass {};
struct ConcreteSub1: public ConcreteClass
{
static int get() { return 1; }
};
struct ConcreteSub2: public ConcreteClass
{
static int get() { return 2; }
};
template< typename T >
struct ValueTraits< T, 123, typename std::enable_if<
std::is_base_of< ConcreteClass, T >::value >::type >
{
static int getValue() { return T::get(); }
};
int main()
{
// prints 1, 2, 0
printf( "%d, %d, %d\n",
ValueTraits< ConcreteSub1, 123 >::getValue(),
ValueTraits< ConcreteSub2, 123 >::getValue(),
ValueTraits< int, 123 >::getValue() );
return 0;
}
The problem is, I can't add an additional dummy type argument to ValueTraits
, since it's part of a library which actually provides this ValueTraits
for me to specialize.
So my question is, can I perform this specialization with the original version of ValueTraits
taking only typename
and int
, and how?
EDIT: To clarify, I am not the user of ValueTraits
either - the library provides it for me to specialize, and then the library again instantiates it with my types to get the behavior I've defined in my specializations. So I have no control on neither the definition of ValueTraits
nor on the way it's used afterwards.