如何为所有 IOStream 操纵器通用定义插入运算符C++
How to Generically Define Insertion Operators for all C++ IOStream Manipulators?
All,
为什么以下代码无法为"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 <<std::endl"中的"运算符<<"不匹配
我希望代码能够实例化 std::endl 的"运算符<<",就像它对原语 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<<
重载定义为接受函数指针的成员函数;特别是:
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;
}
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- 为 std::vector 编写自定义插入函数
- 将带有模板的自定义类插入到 std::map 中
- 如何将标准::矢量插入具有自定义排序功能的 std::set 中
- 无法使用带有 std::move 的自定义删除器插入 std::unique_ptr
- 为什么push_back函数不会将值插入到具有定义大小的向量中
- 使用自定义比较器C++映射,不插入所有元素
- 是否有任何快捷键可以插入函数的定义
- 尝试将用户定义的向量类型插入用户定义的类型向量
- 当我添加自定义比较器时,无法插入新元素以设置
- 在 Codelite 中的类定义后自动插入分号
- 在自定义源和 SmartTee 之间插入筛选器会泄漏 COM 对象
- 为什么插入用户定义的破坏者需要用户定义的复制构造函数
- 自定义char*插入功能多次运行时会产生运行时错误
- 插入同一键时,自定义类的unordered_map不会导致错误
- 正在将自定义传输插入gRPC
- 如何将向量插入2D矢量的定义位置
- 不能使用 pimpl 习语将用户定义的向量插入到封装的向量中
- std::copy的自定义插入器
- 如何为所有 IOStream 操纵器通用定义插入运算符C++