Reputation: 2524
I would like to create a template that checks if a class type is a primitive or not (int, char, float, float***, ect...). The reason for this is to prevent another template from trying to extend primitives and cause a compile-time error. So far I have something along the lines of:
#include <typeinfo>
template<typename T>
struct is_primitive{
const static bool value=std::is_fundamental<T>::value;
};
Obviously this just forwards the result from is_fundamental right now. I'd like to add remove_pointer, remove_reference, ect... to strip all of those extra modifiers of the input class. What are all the removals necessary to make T as bare as possible?
Alternatively, a solution like the following would be equally outstanding:
template<typename T>
struct is_inheritable{
const static bool value=???;
};
But I'm pretty sure the set of uninheritable classes equals the set of primitive classes.
Upvotes: 1
Views: 452
Reputation: 218780
It sounds to me like you want std::is_class<T>
. One can only inherit from class types. This is a diagram that depicts the C++11 type classification traits: Here http://howardhinnant.github.io/TypeHiearchy.pdf
http://howardhinnant.github.io/TypeHiearchy.pdf
Upvotes: 5
Reputation: 56863
I'd suggest you try to focus on detecting the properties of a type that are required to be inheritable in your case instead of thinking about detecting those types that are not. With any luck, your class needs additional properties from your base class that can be checked because your derived class will need to call at least one constructor of the base class.
Try using is_constructible
or some related type trait:
// check that T::T(std::string,int); exists:
std::is_constructible< T, std::string, int >::value
// or these direct traits for the usual suspects...
std::is_default_constructible< T >::value
std::is_copy_constructible< T >::value
std::is_move_constructible< T >::value
For your other question, if it is still relevant after the above, check out std::decay
and combine it with other traits to strip the type as needed:
template< typename T, typename = void >
struct strip
{
typedef T type;
};
template< typename T >
struct strip< T, typename std::enable_if<
!std::is_same< typename std::decay< T >::type, T >::value
>::type >
: strip< typename std::decay< T >::type >
{
};
template< typename T >
struct strip< T, typename std::enable_if<
std::rank< T >::value != 0
>::type >
: strip< typename std::remove_all_extents< T >::type >
{
};
template< typename T >
struct strip< T, typename std::enable_if< std::is_pointer< T >::value >::type >
: strip< typename std::remove_pointer< T >::type >
{
};
typedef const int*(&Test)[42];
static_assert( std::is_same< typename strip< Test >::type, int >::value, "" );
but of couse you need to figure out what exactly is appropriate in your case.
Upvotes: 1
Reputation: 2524
template <typename T>
struct remove_all { typedef typename std::remove_cv<T>::type type; };
template <typename T>
struct remove_all<T*> { typedef typename remove_all<T>::type type; };
template <typename T>
struct remove_all<T&> { typedef typename remove_all<T>::type type; };
template <typename T>
struct remove_all<T&&> { typedef typename remove_all<T>::type type; };
template<typename T>
struct is_primitive{
typedef typename remove_all<T>::type TF;
const static bool value=std::is_fundamental<TF>::value;
};
remove_all struct discussion found here.
Upvotes: 0