[英]How to Generically Define Insertion Operators for all C++ IOStream Manipulators?
所有,
為什么以下代碼無法為'std :: endl'編譯,但它適用於所有其他插入類型?
#include <sstream> // ostringstream
/// @brief A class that does streamed, formatted output via 'operator<<'.
class My_Stream
{
public:
/// @brief A member method that manipulates the underlying stream.
void foo()
{
m_oss << "foo_was_here; ";
}
private:
/// @brief The underlying stream.
std::ostringstream m_oss;
/// @brief 'operator<<' is a friend.
template< typename T >
friend My_Stream& operator<<( My_Stream& a_r_my_stream,
const T& a_r_value );
};
/// @brief A manipulator that calls a class method.
My_Stream& manipulator_foo( My_Stream& a_r_my_stream )
{
a_r_my_stream.foo();
return a_r_my_stream;
}
/// @brief The generic insertion operator.
template< typename T >
My_Stream& operator<<( My_Stream& a_r_my_stream,
const T& a_r_value )
{
a_r_my_stream.m_oss << a_r_value;
return a_r_my_stream;
}
/// @brief Define an iostream-like manipulator for my-stream.
typedef My_Stream& ( * my_stream_manipulator ) ( My_Stream& );
/// @brief The specialized 'my_stream_manipulator' insertion operator.
template<>
My_Stream& operator<<( My_Stream& a_r_my_stream,
const my_stream_manipulator& a_r_manipulator )
{
return a_r_manipulator( a_r_my_stream );
}
int main( int argc, char* argv[] )
{
My_Stream my_stream;
my_stream << 'c'; // char
my_stream << "string"; // c-string
my_stream << 1u; // unsigned int
my_stream << -1; // signed int
my_stream << 5.3f; // float
my_stream << -23.345; // double
my_stream << std::boolalpha; // std::ios_base manipulator
my_stream << std::endl; // std::ostream manipulator
my_stream << manipulator_foo; // my_stream manipulator
return 0;
}
我收到以下G ++ 4.5錯誤:
willo:〜/ test_cpp $ g ++ -Wall test_overloaded_insertion_manipulators.cpp test_overloaded_insertion_manipulators.cpp:在函數'int main(int,char **)'中:test_overloaded_insertion_manipulators.cpp:60:錯誤:'my_stream <中的'operator <<'不匹配<std :: endl'
我希望代碼為std :: endl實例化一個'operator <<',就像它對原語std :: ios_base和我的自定義操縱器一樣。
對於上下文,我正在嘗試創建一個類似於光的API IOStream類,它與當前的IOStream操縱器以及一個或兩個以上的自定義操縱器一起使用。
因為endl
是一個函數模板:
template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
所以標識符本身不是值。 它僅在實例化時變為值(函數指針)。 但是你的operator<<
本身就是一個模板,編譯器沒有可用的類型信息來決定實例化endl
類型。
相比之下,例如boolalpha
是:
ios_base& boolalpha(ios_base& str);
因此它為什么有效。
endl
適用於basic_ostream
,因為它將operator<<
overloads定義為basic_ostream
函數指針的成員函數; 尤其是:
basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
所以在像stream << endl
這樣的調用中,它會從this
類型(即運算符的左側)知道charT
和traits
,並且這將給出它在右側預期的精確類型的函數指針 - 然后它將使用實例化相應版本的endl
。 你可以為你的班級做同樣的事情。
您需要將流操縱器定義為單獨的朋友。
添加這位朋友:
// Note: Untested (don't have a compiler here).
template <class charT, class Traits>
friend My_Stream& operator<<( My_Stream&, std::basic_ostream<charT, Traits>& (*)(std::basic_ostream<charT, Traits>&));
然后你需要定義函數:
template <class charT, class Traits>
My_Stream& operator<<( My_Stream& stream, std::basic_ostream<charT, Traits>& (*manip)(std::basic_ostream<charT, Traits>&))
{
(*manip)(stream.m_oss);
return stream;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.