2017-09-11 100 views
3

我需要在雙引號內打印所有類型的字符串數據,而其他字符串數據不需要雙引號。std :: enable_if_t將字符串與非字符串函數參數分開

這是我的函數來檢查參數是否是一個字符串。

template<class T> 
struct is_str : std::integral_constant<bool, false> {}; 
template<> struct is_str<char*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<wchar_t*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const char*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const wchar_t*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<std::string> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const std::string> : std::integral_constant<bool, true> {}; 
template<> struct is_str<std::wstring> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const std::wstring> : std::integral_constant<bool, true> {}; 

,並在打印機功能,我用這樣

template<typename T> 
std::enable_if_t<is_str<T>::value>, std::ostream&> 
    operator<<(std::ostream& xx, const T& ar) 
{ 
    xx << "\"" << ar << "\""; 
    return xx; 
} 

template<typename T> 
std::enable_if_t<!is_str<T>::value>, std::ostream&> 
    operator<<(std::ostream& xx, const T& ar) 
{ 
    xx << ar; 
    return xx; 
} 

上述功能它不與錯誤

無法識別的模板聲明/定義

編譯

有人可以告訴我如何解決這個或更好的方式來處理噸他的情況?

回答

3

格雷厄姆最好是正確的,但還有另外一個(大,恕我直言)的問題。

您並未定義operator<<;你正在重新定義它自己。

據我所知,這是不可能的(重新定義一個函數,編譯器不知道哪個版本的呼叫),當你寫(重新定義的運營商內部)

xx << "\"" << ar << "\""; 

應該是其中的operator<<()版本用過的?新的重新定義(導致循環遞歸)還是舊的?

我認爲退出這個問題的最好方法是避免重新定義operator<<()並定義一個簡單的函數;通過例如,以下print()

template<typename T> 
std::enable_if_t<is_str<T>::value, std::string> print (T const & ar) 
{ 
    std::ostringstream oss; 

    oss << "\"" << ar << "\""; 

    return oss.str(); 
} 

template<typename T> 
std::enable_if_t<!is_str<T>::value, T const &> print (T const & ar) 
{ return ar; } 

並且以這種方式使用它

std::cout << print(std::string{"abc"}) << std::endl; // add quotes 
std::cout << print(1) << std::endl;     // no quotes 

順便:有幾個類,可以是寫一個更緊湊的代碼有用:std::true_type,定義爲std::integral_constant<bool, true>std::false_type,定義爲std::integral_constant<bool, false>

所以,你可以定義is_str如下

template<class T> 
struct is_str : std::false_type {}; 

template<> struct is_str<char*> : std::true_type {}; 
template<> struct is_str<wchar_t*> : std::true_type {}; 
// ... 

OBSERVE還,如果你寫

std::cout << print("abc") << std::endl; // add quotes 

print()不加引號。這是因爲​​不是char const *;這是一個const char[4]

所以,如果你想引號添加到char[N]wchar_t[N]過,你應該添加以下專業

template<std::size_t N> struct is_str<char[N]> : std::true_type {}; 
template<std::size_t N> struct is_str<wchar_t[N]> : std::true_type {}; 
1

你有一個uneeded>在你的代碼(封閉的模板類型說明符)

試試這個:

template<class T> 
struct is_str : std::integral_constant<bool, false> {}; 
template<> struct is_str<char*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<wchar_t*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const char*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const wchar_t*> : std::integral_constant<bool, true> {}; 
template<> struct is_str<std::string> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const std::string> : std::integral_constant<bool, true> {}; 
template<> struct is_str<std::wstring> : std::integral_constant<bool, true> {}; 
template<> struct is_str<const std::wstring> : std::integral_constant<bool, true> {}; 

template<typename T> 
std::enable_if_t<is_str<T>::value, std::ostream&> /* fixed line versus yours */ 
operator<<(std::ostream& xx, const T& ar) 
{ 
    xx << "\"" << ar << "\""; 
    return xx; 
} 

template<typename T> 
std::enable_if_t<!is_str<T>::value, std::ostream&> /* fixed line versus yours */ 
operator<<(std::ostream& xx, const T& ar) 
{ 
    xx << ar; 
    return xx; 
} 
+1

請閱讀@ max66美麗的答案。他深入到代碼中的更多問題:) –