C++ 错误:无法将“std::basic_ostream<char>”左值绑定到“std::basic_ostream<char>&&”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13347530/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
error: cannot bind ‘std::basic_ostream<char>’ lvalue to ‘std::basic_ostream<char>&&’
提问by cross
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.
我已经看过几个关于此的问题,特别是 重载运算符<<:无法将左值绑定到 'std::basic_ostream<char>&&'非常有帮助。它让我知道我的问题是我正在做一些 c++11 无法从中推断出类型的事情。
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.
我认为我的问题的很大一部分是我正在使用的实例化类是模板化的,但最初是从指向非模板基类的指针获得的。这是我从另一个关于如何将模板类对象放入 STL 容器的 stackoverflow.com 问题中提出的建议。
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:
并且,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;
}
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 seemsto still know that i->second
is of the correct type
如果我的输出尝试 print i->second
,它会编译并运行,并且我会看到指针。如果我尝试输出*(i->second)
,我会收到编译错误。在gdb中单步执行时,似乎仍然知道i->second
是正确的类型
(gdb) p i->second
= (DbValueBase *) 0x680900
(gdb) p *(i->second)
warning: RTTI symbol not found for class 'DbValue<std::string>'
= 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.
@PiotrNycz 确实为我在下面提出的问题提供了一个很好的解决方案。然而,尽管当前在进行开发时打印值,但对这些DbValue<>
对象的真正需要是让它们返回正确类型的值,然后我可以将其提供给数据库操作方法。我应该在我最初的问题中提到,印刷是有价值的,但不是我目标的终点。
采纳答案by Bart van Ingen Schenau
Although the debugger correctly identifies *(i->second)
as being of the type DbValue<std::string>
, that determination is made using information that is only available at runtime.
尽管调试器正确识别*(i->second)
为 类型DbValue<std::string>
,但该确定是使用仅在运行时可用的信息进行的。
The compiler only knows that it is working with a DbValueBase&
and has to generate its code on that basis. Therefore, it can't use the operator<<(std::ostream&, const DbValue<T>&)
as that does not accept a DbValueBase
or subclass.
编译器只知道它正在使用 aDbValueBase&
并且必须在此基础上生成其代码。因此,它不能使用operator<<(std::ostream&, const DbValue<T>&)
不接受 aDbValueBase
或子类的 。
For obtaining the contents of a DbValue<>
object through a DbValueBase&
, you might want to loop into the Visitor design pattern.
为了DbValue<>
通过 a获取对象的内容DbValueBase&
,您可能需要循环访问访问者设计模式。
Some example code:
一些示例代码:
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;
};
回答by PiotrNycz
If you want to print object by base pointer - make the ostream operator in base class:
如果要通过基指针打印对象 - 在基类中创建 ostream 运算符:
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();
}
};