Detecting basic_string instantiation
I wrote the following code to determine if a type is an instantiation of std::basic_string
:
template <ty开发者_JAVA技巧pename T>
struct is_string
{
enum { value = false };
};
template <typename charT, typename traits, typename Alloc>
struct is_string<std::basic_string<charT, traits, Alloc> >
{
enum { value = true };
};
Is there a more succinct way to achieve that?
Okay, I found a slightly shorter way:
#include <type_traits>
template <typename T>
struct is_string : std::false_type {};
template <typename charT, typename traits, typename Alloc>
struct is_string<std::basic_string<charT, traits, Alloc> > : std::true_type {};
But maybe others can do even better? :)
With a bit of SFINAE one can even check if the type is derived from some basic_string:
#include <type_traits>
namespace detail
{
template <typename T, class Enable = void>
struct is_string : std::false_type {};
template <typename... T>
struct void_helper { typedef void type; };
template <typename T>
struct is_string<T,
typename void_helper<
typename T::value_type,
typename T::traits_type,
typename T::allocator_type
>::type
>
: std::is_base_of<
std::basic_string<
typename T::value_type,
typename T::traits_type,
typename T::allocator_type
>,
T
>
{};
}
template <typename T>
struct is_string : detail::is_string<T> {};
Another way to do it not so succint as your solution I admit :-), but one that also detects classes derived from basic_string and pointers to string would be:
namespace string_traits
{
typedef char yes_type;
struct no_type
{
char padding[8];
};
no_type string_helper(...);
template <typename charT, typename traits, typename Alloc>
yes_type string_helper(std::basic_string<charT, traits, Alloc>);
template <typename T>
typename std::remove_pointer<T>::type MakeT();
template <typename T>
struct is_string : std::integral_constant<bool,sizeof(string_helper(MakeT<T>()))==sizeof(yes_type)> {};
template <> struct is_string<void> : std::false_type { };
}
class TestString : public std::basic_string<char> { };
class A { };
template <bool b>
void check()
{
cout << (b?"Is string":"Is not string") << endl;
}
int main()
{
using namespace string_traits;
//not strings
check<is_string<void>::value>();
check<is_string<int>::value>();
check<is_string<int(&)[2]>::value>();
check<is_string<string(&)[2]>::value>();
check<is_string<string**>::value>();
check<is_string<A>::value>();
//strings
check<is_string<string>::value>();
check<is_string<TestString>::value>();
check<is_string<TestString&>::value>();
check<is_string<TestString*>::value>();
check<is_string<std::wstring>::value>();
check<is_string<string*>::value>();
check<is_string<string&>::value>();
}
精彩评论