5

我寫了下面的代碼,以確定一個類型的std::basic_string一個實例:檢測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 }; 
}; 

有沒有更簡潔的方式來實現這一目標?

+3

這看起來對我來說是規範的。 – 2011-02-23 13:10:57

+1

這是否正確地檢測到'basic_string'的實例化,它的第二個和第三個模板參數與默認值不同? – 2011-02-23 13:26:49

+0

@Steve好點,希望修正,看我的編輯。 – fredoverflow 2011-02-23 13:31:43

回答

2

好吧,我發現了一個稍短的方式:

#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 {}; 

但也許別人可以做得更好? :)

0

有了一點SFINAE一個甚至可以檢查的種類從一些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

現在是這個「更succint」?大聲笑。無論如何,我認爲代碼中存在錯誤。如果派生類聲明'value_type'或其他名稱之一,它將隱藏'basic_string'和'is_string'將觸發派生類'。 – 2011-02-26 12:18:43

+0

實際上,如果你重新定義了value_type,traits_type或allocator_type,你並沒有任何理由讓is_string成爲true。我沒有聲稱它更簡潔,只是它也處理派生類:) – filmor 2011-02-28 11:24:36

0

另一種方式來做到這一點並非如此succint爲您的解決方案我承認:-),而是一個也檢測從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>(); 
}