开发者

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>();
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜