Template specialization for templated type - c++

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; };

Related

How to specialize a class template with a template?

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.

Is it possible to change the value of a static const class member by template type?

I don't really know the terminology on this, I'll just do an example:
template <typename T>
struct value_holder {
T value;
static const bool is_integer = ??; // if T is int or long set this to true, else set false
}
so that when I do
value_holder<float> floaty;
std::cout << floaty.is_integer << "\n";
it would print 0
How would I have to define the member is_integer so it would do that?
You can use std::is_same to do that.
It follows a minimal, working example:
#include<type_traits>
template <typename T>
struct value_holder {
T value;
static const bool is_integer = std::is_same<int, T>::value or std::is_same<long, T>::value;
};
int main() {
static_assert(value_holder<int>::is_integer, "!");
static_assert(not value_holder<char>::is_integer, "!");
}
Another possible approach is based on template specialization. Something along this way should work:
template <typename T>
struct value_holder {
T value;
static const bool is_integer = false;
};
template <>
struct value_holder<int> {
int value;
static const bool is_integer = true;
};
template <>
struct value_holder<long> {
long value;
static const bool is_integer = true;
};
Anyway it's a bit more verbose from my point of view and can be annoying if your class contains more than a couple data members.
As Quentin's answer says, you use a type trait. std::is_integral makes sense in your example:
template <typename T>
struct value_holder {
T value;
static constexpr bool is_integer = std::is_integral<T>::value;
};
That doesn't exactly match your comment though. If you really want to have is_integer be true only for int or long then you could define a custom type trait:
template <typename T>
struct is_int_or_long : std::false_type {};
template <>
struct is_int_or_long<int> : std::true_type {};
template <>
struct is_int_or_long<long> : std::true_type {};
template <typename T>
struct value_holder {
T value;
static constexpr bool is_integer = is_int_or_long<T>::value;
};
Of course, that could be shortened by using the std::is_same trait:
template <typename T>
struct value_holder {
T value;
static constexpr bool is_integer = std::is_same<T, int>::value || std::is_same<T, long>::value;
};
You're looking for type traits. std::is_integral might be of interest to you.

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

Detect if a given type is a function type in C++03

Is there any way to detect at compile-time whether a given type is a function type in C++03 when I don't know the function's signature? If so, how?
(I only need this for free functions, not member functions.)
I found a solution myself, thanks to Kerrek SB's initial hint:
template<class T> struct is_function
{
private:
static T &declval;
static char (&test(T *))[2];
template<class U>
static char (&test(U const &))[1];
public:
static bool const value = sizeof(test(declval)) > 1;
};
template<> struct is_function<void> { static bool const value = false; };
template<class T> struct is_function<T const> : is_function<T> { };
template<class T> struct is_function<T volatile> : is_function<T> { };
template<class T> struct is_function<T const volatile> : is_function<T> { };
template<class T> struct is_function<T &> { static bool const value = false; };
Turns out member function pointers are easy too:
template<class> struct is_member_function_pointer { static bool const value = false; };
template<class T> struct is_member_function_pointer<T const> : is_member_function_pointer<T> { };
template<class T> struct is_member_function_pointer<T volatile> : is_member_function_pointer<T> { };
template<class T> struct is_member_function_pointer<T const volatile> : is_member_function_pointer<T> { };
template<class T, class U> struct is_member_function_pointer<T U::*> : is_function<T> { };

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.