How to specialize a class template with a template? - c++

Consider the class template:
template<typename T>
struct A
{
T data;
static const bool flag;
static bool calc_flag()
{
// Default value;
return false;
}
};
template<typename T>
const bool A<T>::flag = A<T>::calc_flag();
And now I'd like to specialize this template for the following class template:
template<char N>
struct B
{
static const bool is_a;
};
template<char N>
const bool B<N>::is_a = N == 'a';
in order to the A<B<N>>::flag will be initialized with the B<N>::is_a. I.e., I'd like to specialize the calc_flag() method for such the case. How could this be done?

You could separate the calculation to an implementation struct and only specialize that
template<class T>
struct calc_flag_impl {
static bool calc_flag() { return false; }
};
template<typename T>
struct A
{
T data;
static const bool flag = calc_flag_impl<T>::calc_flag();
};
Now you can specialize calc_flag_impl
template<char N>
struct calc_flag_impl<B<N>> {
static bool calc_flag() { return B<N>::is_a; }
};
Note: The specialization must exist prior to instantiation of the class template for your type for it to work with static class variables.

Related

Template class with variable number of members in C++

This is more of a curiosity with C++ templates than something useful. It supposed to be a class with a variable number of members. Is it likely that this will be compiled down to direct member access?
// type equality
template <typename X, typename Y> struct Eq { static const bool out = false; };
template <typename X> struct Eq<X, X> { static const bool out = true; };
template <typename First, typename... Rest>
class Table {
First _field;
Table<Rest...> _nextTable;
public:
template <typename T>
T &get() {
if (Eq<First, T>::out)
return (T&)_field;
return (T&)_nextTable.get<T>();
}
};
template<typename First>
class Table<First> {
First _field;
public:
template <typename T>
T &get() {
return _field;
}
};
int main() {
Table<int, double> table;
table.get<double>() = 11.1;
}
return (T&)_nextTable.template get<T>();
http://en.cppreference.com/w/cpp/language/dependent_name

How can i identify if a template parameter argument is instance of another class in a struct within template? C++

I have a .h file with all my templates in it and a .cpp file with my main.
Part of .h templates:
template<int N, int P>
struct BOUND {
static inline int eval(int v) {
//...
return 1;
};
};
template<class K>
struct VAL_x {
static inline int eval(int v) {
//...
return 1;
};
};
template<int L, class K>
struct LIT {
static inline int eval(int v) {
//...
return 1;
};
};
template<class A, class B, class K>
struct ADD {
static inline int comp_b(int v){
// HERE check if class A is LIT or VAL_x
//...
return 2;
};
};
Here is how I call in my main() this template:
int main() {
typedef ADD<VAL_x<BOUND<2,3> >, LIT<2, BOUND<2,3> >, BOUND<2,3> > FORM;
FORM exec_form;
int y = 2;
int bounds = exec_form.comp_b(y);
return 0;
}
How can I know in ADD::comp() function of my struct, if an argument that was passed is instance of a specific class (e.g. LIT<> )? Those arguments can be passed in any order (e.g all arguments could be LIT, or only the second one)
NOTE: there are also other structs apart from VAL_x , LIT, BOUND and ADD.
Option #1
Introduce a separate trait for each class template of interest (C++03 doesn't help here much).
template <bool B> struct bool_constant { static const bool value = B; };
template <bool B> const bool bool_constant<B>::value;
template <typename T> struct is_LIT : bool_constant<false> {};
template <int L, int M> struct is_LIT<LIT<L, M> > : bool_constant<true> {};
template <typename T> struct is_VAL_x : bool_constant<false> {};
template <int K> struct is_VAL_x<VAL_x<K> > : bool_constant<true> {};
template <class A, class B>
struct ADD
{
static inline int comp_b(int v)
{
if (is_LIT<A>::value && is_VAL_x<B>::value)
{
}
return 2;
}
};
DEMO
Option #2
Use a generic custom trait, whose specialization detects if the type passed is an instantiation of the specified template-template parameter (it is if the specialization matches, i.e., T is an instantiation of class template X):
template <template <int> class X, typename T>
struct is_template { static const bool value = false; };
template <template <int> class X, int N>
struct is_template<X, X<N> > { static const bool value = true; };
template <typename A, typename B>
struct ADD
{
static inline int comp_b(int v)
{
if (is_template<VAL_x, A>::value && is_template<LIT, B>::value)
{
}
return 2;
}
};
DEMO 2
Option #3
Use tag-dispatching, possibly add overloads for other class templates that return true/false, making it similar to Option #1. This solution also relies on overload resolution, that prefers more specialized function templates over those less constrained/generic.
template <typename T> struct tag {};
template <typename A, typename B>
struct ADD
{
static inline int comp_b(int v)
{
return comp_b(v, tag<A>(), tag<B>());
}
template <int M, int N>
static inline int comp_b(int v, tag<LIT<M> >, tag<VAL_x<N> >)
{
return 1;
}
template <typename T, typename U>
static inline int comp_b(int v, tag<T>, tag<U>)
{
return 2;
}
};
DEMO 3
You could do it like this:
#include <typeinfo>
...
template<class A, class B>
struct ADD {
static inline int comp_b(int v){
// HERE check if class A is LIT or VAL_x
std::cout << ( typeid(A)==typeid(VAL_x) ) << '\n';
return 2;
};
};
where I am using std::type_info, which will print 1, for true evaluation.
Or, with c++11, you could do:
#include <type_traits>
...
if (std::is_same<A, VAL_x>::value)
std::cout << "they are same!\n";
However, you could overload a function or such. Make sure you read this: How do I check my template class is of a specific classtype? and this How to check for the type of a template parameter?

Several levels of nested templates. How do I get this to work?

I'm doing some template meta programming and I have a situation like this, first I have a few classes like :-
template <typename Q>
struct Object {
public:
Q data;
};
template <typename P>
class CircleObject : public Object<const typename P::Circle> {
};
template <typename P>
class SquareObject : public Object<const typename P::Circle> {
};
template <typename P>
class Storage {
public:
typedef CircleObject<P> MyCircle;
typedef SquareObject<P> MySquare;
};
Now, I'm trying to define some traits of these objects as such :-
template <typename P>
struct CircleTraits<Storage<P> > {
template <typename otype>
struct IsCircle {
static const bool VALUE = false;
};
};
template <typename P>
struct CircleTraits<Storage<P> >::IsCircle<Storage<P>::MyCirlce> {
static const bool VALUE = true;
};
However, this is incorrect (compile errors). I've tried a trial and error method of putting typenames and template parameters everywhere but without a firm understanding of template specializations, I'm not really able to fix this. Can someone help here?
What I'm hoping to achieve in a later function is something like :-
typedef Storage<RedObjects> RedStorage;
template <typename SpecializedStorage>
class Processor {
typedef CircleTraits<typename SpecializedStorage> MyCircleTraits;
template <typename ObjectType>
void foo(ObjectType& data);
};
template <typename SpecializedStorage>
template <typename ObjectType>
void foo(ObjectType& data) {
if (MyCircleTraits::template IsCircle<ObjectType>::VALUE) {
// do something about the damn circles
}
}
I think you cant do it like that, You probably should use SFINAE to solve something like this:
//C++11 version
template<typename T>
struct IsCircle
{
private:
template<typename Z>
constexpr static bool _is(typename Z::MyCirlce*) //if Z dont have `MyCirlce` then this function is removed
{
return true;
}
template<typename Z>
constexpr static bool _is(...) //fallback function
{
return false;
}
public:
static const bool VALUE = _is<T>(nullptr);
};
//C++98 version
template<typename T>
struct IsCircle
{
private:
struct a { char a; }; //size ~1
struct b { char a[8]; }; //size ~8
template<typename Z>
static b _is(typename Z::MyCirlce*);
template<typename Z>
static a _is(...);
public:
static const bool VALUE = sizeof(_is<T>(0)) == sizeof(b);
};

Template specialization for templated type

I have a struct that contains a trait about a type:
template<typename T> struct x_trait { static const bool has_x = true; };
That is correct for all types but for a certain template type. For that certain template type I want to change the trait:
template<> struct x_trait<tt_type<int>> { static const bool has_x = false; };
So far, so good. But the tt_type itself takes different template parameters. Is there a way to set the x_trait for all templated tt_types? Right now my only way out is to list all types:
template<> struct x_trait<tt_type<char>> { static const bool has_x = false; };
template<> struct x_trait<tt_type<short>> { static const bool has_x = false; };
template<> struct x_trait<tt_type<int>> { static const bool has_x = false; };
template<> struct x_trait<tt_type<long>> { static const bool has_x = false; };
You can partially specialise the x_trait template for all specialisations of the tt_type template:
template<typename T>
struct x_trait<tt_type<T>> { static const bool has_x = false; };

how to implement is_pointer?

I want to implement is_pointer. I want something like this:
template <typename T >
bool is_pointer( T t )
{
// implementation
} // return true or false
int a;
char *c;
SomeClass sc;
someAnotherClass *sac;
is_pointer( a ); // return false
is_pointer( c ); // return true
is_pointer( sc ); // return false
is_pointer( sac ); // return true
How can I implement it?
Thanks
template <typename T>
struct is_pointer_type
{
enum { value = false };
};
template <typename T>
struct is_pointer_type<T*>
{
enum { value = true };
};
template <typename T>
bool is_pointer(const T&)
{
return is_pointer_type<T>::value;
}
Johannes noted:
This is actually missing specializations for T *const, T *volatile and T * const volatile i think.
Solution:
template <typename T>
struct remove_const
{
typedef T type;
};
template <typename T>
struct remove_const<const T>
{
typedef T type;
};
template <typename T>
struct remove_volatile
{
typedef T type;
};
template <typename T>
struct remove_volatile<volatile T>
{
typedef T type;
};
template <typename T>
struct remove_cv : remove_const<typename remove_volatile<T>::type> {};
template <typename T>
struct is_unqualified_pointer
{
enum { value = false };
};
template <typename T>
struct is_unqualified_pointer<T*>
{
enum { value = true };
};
template <typename T>
struct is_pointer_type : is_unqualified_pointer<typename remove_cv<T>::type> {};
template <typename T>
bool is_pointer(const T&)
{
return is_pointer_type<T>::value;
}
...but of course this is just reinventing the std::type_traits wheel, more or less :)
From Dr. Dobbs.
template <typename T>
struct is_pointer
{ static const bool value = false; };
template <typename T>
struct is_pointer<T*>
{ static const bool value = true; };
You can't do exactly what you want to do. You'll have to use this like:
is_pointer<int*>::value
It's not possible to determine this at run time.
template <typename T>
bool is_pointer(T const &t) // edited: was "T t"; see the comments
{
return false;
}
template <typename T>
bool is_pointer(T *t)
{
return true;
}
You might not believe it, but it works. The reason is that the most specific template implementation will be chosen, which is the one which takes the pointer type.
You can use "typeid" operator defined in typeinfo.h for this.
check this link : http://en.wikipedia.org/wiki/Typeid
The typeid operator will give an object of std::type_info class, which has a name() function returning char *. Once you get the type in string form, you can identify the pointer easily.
Hope it helps.
Romil.