Using a static_assert to determine if a specific template parameter is a specific untyped class template
c++, c++11
Solution
There are three ways of solving your problem, one would be an implementation of `is_specialization_of`, the other involves making your function take a `std::basic_string<T1,T2,T3>` instead of `TString`, and the third has the same philosophy as the 2nd solution; make a template matchable only by `std::basic_string`.
`is_base_of` isn't sufficient in your example because of two reasons:
`is_base_of` is used to see if type `U` is derived from `T` (or if it's the same type), in your snippet there is no inheritance involved.
`std::basic_string` isn't a complete type and therefore can't be used with `is_base_of` at all (which you already pointed out).
solution #1
`is_specialization_of` would be used to check whether type `U` is a specialization of the incomplete type `T`. It's quite easy to implement it using a template-template class, as in the below example.
as noted by @SebastianRedl variadic templates are not available using VS2012, see the other solutions (which are not as generic but still sufficient to your needs).
#include <type_traits>
#include <iostream>
#include <string>
template<template<typename...> class T, typename U>
struct is_specialization_of : std::false_type { };
template<template<typename...> class T, typename... Ts>
struct is_specialization_of<T, T<Ts...>> : std::true_type { };
int
main (int argc, char *argv[])
{
std::cerr << is_specialization_of<std::basic_string, std::string >::value << std::endl;
std::cerr << is_specialization_of<std::basic_string, std::wstring>::value << std::endl;
std::cerr << is_specialization_of<std::basic_string, std::istream>::value << std::endl;
}
output
1
1
0
solution #2
template <typename T1, typename T2, typename T3>
void strings_only_please(std::basic_string<T1,T2,T3>) {
// ...
}
Sure, the above won't result in a nice `static_assert` error - but it is sufficient for your needs and does what you want; the function is only callable by types who specialize `std::basic_string`.
solution #3
template<typename T>
struct is_basic_string : std::false_type { };
template<typename T1, typename T2, typename T3>
struct is_basic_string<std::basic_string<T1,T2,T3>> : std::true_type { };
...
is_basic_string<std::string >::value // true
is_basic_string<std::istream>::value // false
Problem
I'd like to have a function that restricts the parameters to be only types that derive from a specific templated class. In this case, `basic_string` (from the STL-docs). For example, a `wstring` is declared: ``` typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring; ``` The basic idea would be something like this: ``` template <class TString> void strings_only_please(TString message) { static_assert(is_base_of<basic_string, TString>::value, "Not a string type!"); } ``` Of course, that doesn't compile though as basic_string hasn't been specified ... it needs a real type. (While I could likely just hard code the few actual string types, I'm looking for a general solution to this pattern.) I'm using Visual Studio 2012 and would ideally like the code to be portable to other modern C++ compilers, like GCC.