I would like to check if a certain template specialization exist or not, where the general case is not defined.
Given:
template <typename T> struct A; // general definition not defined
template <> struct A<int> {}; // specialization defined for int
I would like to define a struct like this:
template <typename T>
struct IsDefined
{
static const bool value = ???; // true if A<T> exist, false if it does not
};
Is there a way to do that (ideally without C++11)?
Thanks
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
It is possible in C++ to get a special behavior for a particular data type. This is called template specialization. Template allows us to define generic classes and generic functions and thus provide support for generic programming.
An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.
There are ways to restrict the types you can use inside a template you write by using specific typedefs inside your template. This will ensure that the compilation of the template specialisation for a type that does not include that particular typedef will fail, so you can selectively support/not support certain types.
Using the fact that you can't apply sizeof
to an incomplete type:
template <class T, std::size_t = sizeof(T)>
std::true_type is_complete_impl(T *);
std::false_type is_complete_impl(...);
template <class T>
using is_complete = decltype(is_complete_impl(std::declval<T*>()));
See it live on Coliru
Here is a slightly clunky, but working C++03 solution:
template <class T>
char is_complete_impl(char (*)[sizeof(T)]);
template <class>
char (&is_complete_impl(...))[2];
template <class T>
struct is_complete {
enum { value = sizeof(is_complete_impl<T>(0)) == sizeof(char) };
};
See it live on Coliru
This is an alternative implementation always using the same trick @Quentin used
C++11 version
template<class First, std::size_t>
using first_t = First;
template<class T>
struct is_complete_type: std::false_type {};
template<class T>
struct is_complete_type<first_t<T, sizeof(T)>> : std::true_type {};
Example on wandbox
Tentative C++03 version which does not work
template<typename First, std::size_t>
struct first { typedef First type; };
template<typename T>
struct is_complete_type { static const bool value = false; };
template<typename T>
struct is_complete_type< typename first<T, sizeof(T)>::type > { static const bool value = true; };
The error in this case is
prog.cc:11:8: error: template parameters not deducible in partial specialization: struct is_complete_type< typename first::type > { static const bool value = true; }; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
prog.cc:11:8: note: 'T'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With