错误:无法将'std :: basic_ostream <char>'左值绑定到'std :: basic_ostream <char> &&'

cro*_*oss 13 c++ templates

我已经看过几个关于这个的问题,特别是 重载运算符<<:无法将左值绑定到'std :: basic_ostream <char> &&' 非常有帮助.它让我知道我的问题是我正在做一些c ++ 11无法从中推断出类型的东西.

我认为我的问题很大一部分是我正在使用的实例化类是模板化的,但最初是从指向非模板基类的指针获得的.这是我从另一个stackoverflow.com问题中建议的关于如何将模板类对象放入STL容器的问题.

我的课程:

class DbValueBase {
  protected:
    virtual void *null() { return NULL; }   // Needed to make class polymorphic
};

template <typename T>
class DbValue : public DbValueBase {
  public:
    DbValue(const T&val)  { data = new T(val); }
    ~DbValue() { if (data) delete data; }

    T   *data;

    const T&    dataref() const { return *data; } 

    friend std::ostream& operator<<(std::ostream& out, const DbValue<T>& val)
    {
        out << val.dataref();
        return out;
    }
}
Run Code Online (Sandbox Code Playgroud)

并且,database.cc:530:90: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’发生编译错误的代码片段:

//nb:  typedef std::map<std::string,DbValueBase*>  DbValueMap;
    const CommPoint::DbValueMap&    db_values = cp.value_map();
    for (auto i = db_values.cbegin() ; i != db_values.cend() ; i++) {
        // TODO: Need to implement an ostream operator, and conversion
        // operators, for DbValueBase and DbValue<>
        // TODO: Figure out how to get a templated output operator to
        // work... 
 //     DbValue<std::string> *k = dynamic_cast<DbValue<std::string>*>(i->second);
        std::cerr << "  Database field " << i->first << " should have value " << *(i->second) << endl;
    }
Run Code Online (Sandbox Code Playgroud)

如果我的输出尝试打印i->second,它编译并运行,我看到指针.如果我尝试输出*(i->second),我得到编译错误.当单步执行gdb时,它似乎仍然知道它i->second是正确的类型

(gdb) p i->second
$2 = (DbValueBase *) 0x680900
(gdb) p *(i->second)
warning: RTTI symbol not found for class 'DbValue<std::string>'
$3 = warning: RTTI symbol not found for class 'DbValue<std::string>'
{_vptr.DbValueBase = 0x4377e0 <vtable for DbValue<std::string>+16>}
(gdb) quit
Run Code Online (Sandbox Code Playgroud)

我希望我做的事情有些巧妙.但是,它比我似乎能够自己解决这个问题更复杂.其他人看到我做错了什么或不完整的事情?

编辑:

@PiotrNycz确实为我提出的问题提供了一个很好的解决方案.但是,尽管当前正在进行开发时打印值,但对这些DbValue<>对象的真正需求是让它们返回正确类型的值,然后我可以将其提供给数据库操作方法.我应该提到,在我原来的问题中,印刷是有价值的,但不是我的目标的终点.

Bar*_*nau 3

尽管调试器正确地识别*(i->second)为 类型DbValue<std::string>,但该确定是使用仅在运行时可用的信息做出的。

编译器只知道它正在使用 aDbValueBase&并且必须在此基础上生成其代码。因此,它不能使用operator<<(std::ostream&, const DbValue<T>&)不接受 aDbValueBase或 子类的 as 。


DbValue<>为了通过 a获取对象的内容DbValueBase&,您可能需要循环进入访问者设计模式。

一些示例代码:

class Visitor {
public:
    template <typename T>
    void useValue(const T& value);
};

class DbValueBase {
public:
    virtual void visit(Visitor&) = 0;
};

template <class T>
class DbValue : public DbValueBase {
pblic:
    void visit(Visitor& v) {
        v.useValue(m_val);
    }
private:
    T m_val;
};
Run Code Online (Sandbox Code Playgroud)