2017-09-11 6 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<<を定義していません。あなたはそれ自身を呼び出すことを再定義しています。

として、私の知る、それは不可能です(この関数を再定義する、コンパイラは、バージョンの呼び出しを知らない)、あなたは(再定義演算子内)書く

operator<<()のバージョンがあるべき
xx << "\"" << ar << "\""; 

中古?新しい再定義された(ループ再帰を引き起こす)または古いもの?

私はこの問題を終了するための最良の方法は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>と定義される。

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 {}; 
// ... 

はあなたが

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

を書く場合print()は引用符を追加していないこともを観察し、以下のように

だから、is_strを定義することができます。

​​が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の美しい答えをお読みください。彼はあなたのコードでより多くの問題に深く入りました:) –

関連する問題