Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
578 views
in Technique[技术] by (71.8m points)

c++ - error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’

I have already looked at a couple questions on this, specifically Overloading operator<<: cannot bind lvalue to ‘std::basic_ostream<char>&&’ was very helpful. It let me know that my problem is I'm doing something that c++11 can't deduce the type from.

I think a big part of my problem is that the instantiated class I'm working with, is templated, but originally obtained from a pointer to a non-template base class. This is something I did advised from another stackoverflow.com question about how to put template class objects into an STL container.

My classes:

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;
    }
}

And, the code snippet where the compile error database.cc:530:90: error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’ occurs:

//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;
    }

If my output tries to print i->second, it compiles and runs, and I see the pointer. If I try to output *(i->second), I get the compile error. When single-stepping in gdb, it seems to still know that i->second is of the correct type

(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

I'm hoping that I'm doing something subtly wrong. But, it's more complicated than I seem to be able to figure it out on my own. Anyone else see what thing(s) I've done wrong or incompletely?

Edit:

@PiotrNycz did give a good solution for my proposed problem below. However, despite currently printing values while doing development, the real need for these DbValue<> objects is to have them return a value of the correct type which I can then feed to database operation methods. I should've mentioned that in my original question, that printing is of value, but not the end of my goal.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you want to print object by base pointer - make the ostream operator in base class:

class DbValueBase {
  protected:
    virtual ~DbValueBase() {}
    virtual void print(std::ostream&) const = 0;
    friend std::ostream& operator << (std::ostream& os, const DbValueBase & obj)
    {
       obj.print(os); return os;
    }
};

template <typename T>
class DbValue : public DbValueBase {
  public:
    void print(std::ostream& os) const 
    {
        out << dataref();
    }
};

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...