简体   繁体   中英

Check if a type is std::basic_string<T> at compile time in C++

I have is_string defined as follow in my C++ code:

#include <string>

template <typename T>
struct is_string
{
    static const bool value = false;
};

template <class T, class Traits, class Alloc>
struct is_string<std::basic_string<T, Traits, Alloc>>
{
    static const bool value = true;
};

int main()
{
    std::cout << is_string<std::string>::value << std::endl;
    std::cout << is_string<std::wstring>::value << std::endl;

    return 0;
}

It is true for both std::string and std::wstring .

But I need a predicate like this:

is_string<char, std::string>::value //to be true
is_string<char, std::wstring>::value //to be false
is_string<wchar_t, std::string>::value //to be false
is_string<wchar_t, std::wstring>::value //to be true

Is it possible to implement it?

Try this:

template <typename T, typename S>
struct is_string
{
  static const bool value = false;
};

template <class T, class Traits, class Alloc>
struct is_string<T, std::basic_string<T, Traits, Alloc>>
{
  static const bool value = true;
};

In this specific case, a simpler solution would be:

template<class T, class S>
using is_string = std::is_same<T, typename S::value_type>;

(However, it doesn't check that the second type is actually a string, if that is fine with you - this solution checks if the second type is any container that holds elements of the first type)

Firstly, you need to make is_string taking two template parameters.

template <typename T, typename = void>
struct is_string
{
    static const bool value = false;
};

template <class T, class Traits, class Alloc>
struct is_string<std::basic_string<T, Traits, Alloc>, void>
{
    static const bool value = true;
};

Then

template <class T, template <typename, typename, typename> class STRING>
struct is_string<T, STRING<T, std::char_traits<T>, std::allocator<T>>>
{
    static const bool value = true;
};

LIVE

Maybe like this:

template<typename x_Char, typename x_String>
struct is_string
{
    static constexpr bool const value
    {
        (
            ::std::is_same_v<::std::string, x_String>
            or
            ::std::is_same_v<::std::wstring, x_String>
        )
        and
        ::std::is_same_v<typename x_String::value_type, x_Char>
    };
};

static_assert(true == is_string<char, std::string>::value); //to be true
static_assert(false == is_string<char, std::wstring>::value); //to be false
static_assert(false == is_string<wchar_t, std::string>::value); //to be false
static_assert(true == is_string<wchar_t, std::wstring>::value); //to be true

online compiler

To deal with allocators:

template<typename x_Char, typename x_String>
struct is_string
: ::std::false_type {};

template<typename x_Char, typename x_CharTrait, typename x_Allocator>
struct is_string<x_Char, ::std::basic_string<x_Char, x_CharTrait, x_Allocator>>
: ::std::true_type {};

online compiler

Here is a C++17 version.

namespace impl
{
    // decay_t will remove const, & and volatile from the type
    template<typename T>
    inline constexpr bool is_string_class_decayed = false;

    template<typename... T>
    inline constexpr bool is_string_class_decayed<std::basic_string<T...>> = true;
} // namespace impl

template<typename T>
inline constexpr bool is_string_class = impl::is_string_class_decayed<std::decay_t<T>>;

template <typename TChar, typename TString>
inline constexpr bool is_string = is_string_class<TString> && std::is_same_v<TChar, TString::value_type>;


// Compile-time tests, you don't even need to write unit-tests to know it all works as expected
static_assert(is_string_class<std::string>);
static_assert(is_string_class<const std::wstring&>); // that's why we need decay_t
static_assert(!is_string_class<int>);
static_assert(!is_string_class<const double>);
static_assert(!is_string_class<const char*>);
static_assert(!is_string_class<std::vector<char>>);

static_assert(is_string<char, std::string>);
static_assert(is_string<wchar_t, std::wstring>);
static_assert(!is_string<char, std::wstring>);
static_assert(!is_string<wchar_t, std::string>);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM