Basic_string Control Discovery

I wrote the following code to determine if a type is an instance std::basic_string:

template <typename 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 concise way to achieve this?

+5
source share
3 answers

Ok, 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? :)

+2
source

With a little SFINAE, you can even check to see 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> {};
0
source

, , :-), , , basic_string , :

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
source

All Articles