How to decide if a template specialization exist
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
How to test if exists a template function specialization
You could do it by placing a static_assert
in the primary function template with a little trick that will assure that your program is not ill formed, stolen shamelessly from here :
template <typename...> struct always_false : std::false_type {};
template<typename T, typename U> double convert(double) {
static_assert(always_false<T, U>::value, "No specialization exists!");
}
template <> double convert<Kilometer, Mile>(double val) { return val/1609.344; }
template <> double convert<Mile, Kilometer>(double val) { return 1609.344*val; }
Live Demo
Check if a template has a specialization for a given type
@BartekBanachewicz the idea is to provide user friendly compiler errors through asserts.
If i can check (Following with the point_2d example) if the coordinates passed are addable
(That is, a specialization of add metafuncion is or not defined for that coordinates),
I can provide more readable errors like "That coordinates are not addable. point_2d needs
addable coordinates for point addition", instead of the common horrible template instantation errors.
Given that this is the motivation of your question would not this be an
easier and more direct solution:
#include <type_traits>
template<typename LHS , typename RHS>
using cannot_add = std::integral_constant<bool,std::is_same<LHS,LHS>::value>;
template<typename LHS , typename RHS>
struct add
{
/* Assert some expressively named condition that is always false
but is dependent on a template parameter.
*/
static_assert(!cannot_add<LHS,RHS>::value,
"Types are not addable. Need specialization");
};
template<typename T1 , T1 VALUE1 , typename T2 , T2 VALUE2>
struct add<std::integral_constant<T1,VALUE1>,std::integral_constant<T2,VALUE2>>
: public std::integral_constant<
typename std::common_type<T1,T2>::type,
VALUE1+VALUE2
> {};
int main()
{
add<std::integral_constant<int,1>,std::integral_constant<int,2>> x; // Line 25
add<float,float> y; // Line 26
return 0;
}
GCC 4.8.1 diagnoses:
main.cpp:26:19: required from here
main.cpp:12:2: error: static assertion failed: Types are not addable. Need specialization
Clang 3.3 diagnoses:
main.cpp:12:2: error: static_assert failed "Types are not addable. Need specialization"
static_assert(!cannot_add<LHS,RHS>::value,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:26:19: note: in instantiation of template class 'add<float, float>' requested here
add<float,float> y; // Line 26
^
Check if class is a template specialization?
Here's one where you can provide the template to be matched against :
template <class T, template <class...> class Template>
struct is_specialization : std::false_type {};
template <template <class...> class Template, class... Args>
struct is_specialization<Template<Args...>, Template> : std::true_type {};
static_assert(is_specialization<std::vector<int>, std::vector>{}, "");
static_assert(!is_specialization<std::vector<int>, std::list>{}, "");
Check if valid template specialization
The following is easier and works:
template<template<typename...> class C, typename... T>
struct is_valid_specialization {
typedef struct { char _; } yes;
typedef struct { yes _[2]; } no;
template<template<typename...> class D>
static yes test(D<T...>*);
template<template<typename...> class D>
static no test(...);
constexpr static bool value = (sizeof(test<C>(0)) == sizeof(yes));
};
Live example
C++ concept to check for derived from template specialization
De-_Ugly
-fied rom MSVCSTL:
template <template <class...> class Template, class... Args>
void derived_from_specialization_impl(const Template<Args...>&);
template <class T, template <class...> class Template>
concept derived_from_specialization_of = requires(const T& t) {
derived_from_specialization_impl<Template>(t);
};
which we use to implement the exposition-only type trait is-derived-from-view-interface
from [range.view]/6.
Note that this has the same limitation as the is_specialization_of
trait cited in the OP: it works only with templates that have all type parameters.
[DEMO]
How to know if a type is a specialization of std::vector?
In C++11 you can also do it in a more generic way:
#include <type_traits>
#include <iostream>
#include <vector>
#include <list>
template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};
template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref>: std::true_type {};
int main()
{
typedef std::vector<int> vec;
typedef int not_vec;
std::cout << is_specialization<vec, std::vector>::value << is_specialization<not_vec, std::vector>::value;
typedef std::list<int> lst;
typedef int not_lst;
std::cout << is_specialization<lst, std::list>::value << is_specialization<not_lst, std::list>::value;
}
Related Topics
Fast Multiplication/Division by 2 for Floats and Doubles (C/C++)
What Is the Array Form of 'Delete'
Const Method That Modifies *This Without Const_Cast
Get Private Data Members for Non Intrusive Boost Serialization C++
How to Control My Pc's Fan Speed Using C++ in Vista
What Is the Cin Analougus of Scanf Formatted Input
How to Properly Delete a Pointer to Array
Boost::Asio with Boost::Unique_Future
Disable Sleep Mode in Windows Mobile 6
C++ 128/256-Bit Fixed Size Integer Types
Stl Map Containing References Does Not Compile
Memoized, Recursive Factorial Function
How to Vertically Align Text in Edit Box
Is It Allowed to Cast Away Const on a Const-Defined Object as Long as It Is Not Actually Modified
How to Get at the Exception Information When Using Minidumpwritedump Out-Of-Process