Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用<&书信电报;重载操作系统中的运算符<&书信电报;操作人员_C++_Templates_Gcc - Fatal编程技术网

C++ 使用<&书信电报;重载操作系统中的运算符<&书信电报;操作人员

C++ 使用<&书信电报;重载操作系统中的运算符<&书信电报;操作人员,c++,templates,gcc,C++,Templates,Gcc,我正在编写一个重载>操作符的类,类似于std::istream和std::ostream。前几个功能按预期工作。但是,我想在我自己的类中使用其他std::*流类进行格式化,这会引起一个有趣的问题,我想说,“递归”编译器问题: class SmartStream { public: template <typename F> friend F &operator << (F &in, float f) { in.type ("

我正在编写一个重载>操作符的类,类似于std::istream和std::ostream。前几个功能按预期工作。但是,我想在我自己的类中使用其他std::*流类进行格式化,这会引起一个有趣的问题,我想说,“递归”编译器问题:

class SmartStream
{
public:
    template <typename F> friend F &operator << (F &in, float f)
    {
        in.type ("f");
        in.m_buf.str ("");
        in.m_buf << f;          // This causes a 'recursive' compile call
        in.add (in.m_buf.str ());
        return in;
    }

protected:
    std::ostringstream m_buf;

    void type(const std::string &_type) {};
    void add(const std::string &) {};
};
有两个问题。首先,如代码中所述,这会触发一个不明确的重载。其次,考虑以下几点:

class ExtraStream: public SmartStream
{
public:
    template <typename F> friend F &operator << (F &in, struct tm t)
    {
        in.type ("tm");
        in.m_buf.str ("");
        in.m_buf << t.tm_hour; // Ambiguous overload
        in.add (in.m_buf.str ());
        return in;
    }
};
类外流:公共智能流
{
公众:

模板friend F&operator因此,我认为最简单的方法是使用类似
std::enable_if
的东西限制friend函数,以便它们仅在具有正确父类的流上有效

#include <sstream>
#include <type_traits>

class SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<SmartStream, F>::value, F&>::type
        operator << (F &in, float f) {
            in.type("f");
            in.m_buf.str("");
            in.m_buf << f;
            in.add (in.m_buf.str ());
            return in;
        }

    protected:
        std::ostringstream m_buf;

        void type(const std::string &_type) {};
        void add(const std::string &) {};
};

class ExtraStream: public SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<ExtraStream, F>::value, F&>::type
        operator << (F &in, struct tm t) {
            in.type ("tm");
            in.m_buf.str ("");
            in.m_buf << t.tm_hour;
            in.add (in.m_buf.str ());
            return in;
        }
};

int main() {
    SmartStream ss;
    ExtraStream es;
    struct tm t;

    ss << 3.14f;
    es << 3.14f << t << 3.14;
    // ss << t; // Fails as expected.
}
#包括
#包括
类智能流{
公众:
模板
好友类型名称std::enable_if::type
运算符< P>我把这个贴在上面,因为我觉得这是一个bug,或者至少是C++引用中的一个模糊。Jonathan Wakely想出了一个非常简单的解决方案:

template <typename F> friend F &operator << (F &in, float f)
{
    in.type ("f");
    in.m_buf.str ("");
    using std::operator <<;  // indicate proper operator in the next line
    in.m_buf << f;          
    in.add (in.m_buf.str ());
    return in;
}

template friend F&operator我只浏览了一下您的代码,但您是否尝试了.m_buf.ostrongstream::operator原始代码中的
。您的模板朋友太笼统了,他们会接受任何东西,请在那里更具体一些。@dyp:interest.使用clang++编译很好,但使用g++4.9.0时失败…@5gon12eder:嗯,在.m_buf::os中也没有
tringstream::operator它有点黑,需要(至少对于GCC4.8来说)启用实验性的C++11功能,但它可以工作。@JvO:
enable_,如果boost中存在用于C++11之前版本的编译器的
,您也可以始终创建一个私有实现。(它不依赖于任何新的编译器功能来实现)。如果您想使用
std::cout,这也是必要的
ExtraStream es;

struct tm t1, t2;
float f1, f2;

es << f1 << t1 << f2 << t2; // works
#include <sstream>
#include <type_traits>

class SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<SmartStream, F>::value, F&>::type
        operator << (F &in, float f) {
            in.type("f");
            in.m_buf.str("");
            in.m_buf << f;
            in.add (in.m_buf.str ());
            return in;
        }

    protected:
        std::ostringstream m_buf;

        void type(const std::string &_type) {};
        void add(const std::string &) {};
};

class ExtraStream: public SmartStream {
    public:
        template <typename F>
        friend typename std::enable_if<std::is_base_of<ExtraStream, F>::value, F&>::type
        operator << (F &in, struct tm t) {
            in.type ("tm");
            in.m_buf.str ("");
            in.m_buf << t.tm_hour;
            in.add (in.m_buf.str ());
            return in;
        }
};

int main() {
    SmartStream ss;
    ExtraStream es;
    struct tm t;

    ss << 3.14f;
    es << 3.14f << t << 3.14;
    // ss << t; // Fails as expected.
}
template <typename F> friend F &operator << (F &in, float f)
{
    in.type ("f");
    in.m_buf.str ("");
    using std::operator <<;  // indicate proper operator in the next line
    in.m_buf << f;          
    in.add (in.m_buf.str ());
    return in;
}