如何为所有C++ IOStream操纵器一般定义插入操作符?

Cha*_*cox 6 c++ iostream operator-overloading 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;
}
Run Code Online (Sandbox Code Playgroud)

我收到以下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操纵器以及一个或两个以上的自定义操纵器一起使用.

Pav*_*aev 7

因为endl是一个功能模板:

template <class charT, class traits>
basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
Run Code Online (Sandbox Code Playgroud)

所以标识符本身不是值.它仅在实例化时变为值(函数指针).但是您operator<<自己就是一个模板,并且编译器没有可用的类型信息来决定要实例化哪些类型endl.

相反,例如boolalpha:

ios_base& boolalpha(ios_base& str);
Run Code Online (Sandbox Code Playgroud)

因此它为什么有效.

endl适用于basic_ostream,因为它将operator<<重载定义为获取函数指针的成员函数; 特别是:

basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>& (*pf)(basic_ostream<charT,traits>&));
Run Code Online (Sandbox Code Playgroud)

所以在一个类似的调用中stream << endl,它会知道charTtraits从类型this(即运算符的左侧),并且它将给出它在右侧期望的精确类型的函数指针 - 然后它将用于实例化相应的版本endl.你可以为你的班级做同样的事情.