不明确的运算符 <<
#include "stdafx.h"
#include "Record.h"
template<class T>//If I make instead of template regular fnc this compiles
//otherwise I'm getting an error (listed on the very bottom) saying
// that operator << is ambiguous, WHY?
ostream& operator<<(ostream& out, const T& obj)
{
out << "Price: "
<< (obj.getPrice()) << '\t'//this line causes this error
<< "Count: "
<< obj.getCount()
<< '\n';
return out;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<Record> v;
v.reserve(10);
for (int i = 0; i < 10; ++i)
{
v.push_back(Record(rand()%(10 - 0)));
}
copy(v.begin(),v.end(),ostream_iterator<Record>(cout, "\n"));
return 0;
}
//Record class
class Record
{
private:
int myPrice_;
int myCount_;
static int TOTAL_;
public:
Record(){}
Record(int price):myPrice_(price),myCount_(++TOTAL_)
{/*Empty*/}
int getPrice()const
{
return myPrice_;
}
int getCount()const
{
return myCount_;
}
bool operator<(const Record& right)
{
return (myPrice_ < right.myPrice_) && (myCount_ < right.myCount_);
}
};
int Record::TOTAL_ = 0;
错误 2 错误 C2593:“运算符 <<”不明确
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
operator<<( ostream &, ... )
背后的概念是每个类都可以有自己的重载,以有意义的方式处理特定的类。这意味着您将获得处理 Record 对象的操作符 <<( ostream &, const Record & ) 和操作符<<( ostream &, const std::string & )。 ) 处理标准字符串,
operator<<( ostream &, const FooClass & )
处理 FooClass 对象。这些函数中的每一个都知道如何处理它所声明的对象类型,因为它们中的每一个都需要不同的处理。 (例如getPrice()
/getCount()
用于Record
,或getFoo()
/getBar( )
forFooClass
。)你的模板粗暴地践踏了整个概念。通过将其定义为模板函数(将匹配任何类),您不仅会与标准/您的标准中已有的
operator<<()
的许多定义发生冲突代码库,但所有可能重载。编译器如何决定是否使用运算符<<( ostream &, const std::string & ) 还是您的模板?它不能,所以它绝望地举起双手并放弃。这就是错误告诉你的。
The concept behind
operator<<( ostream &, ... )
is that every class can have its own overload, handling that specific class in a way that make sense.That means you get
operator<<( ostream &, const Record & )
which handles Record objects, andoperator<<( ostream &, const std::string & )
which handles standard strings, andoperator<<( ostream &, const FooClass & )
which handles FooClass objects. Each of these functions knows how to handle the object type it has been declared for, because each of them requires a different handling. (E.g.getPrice()
/getCount()
forRecord
, orgetFoo()
/getBar()
forFooClass
.)Your template is trampling roughshod over the whole concept. By defining it as a template function (which would match any class), you not only collide with the many definitions of
operator<<()
already in the standard / your codebase, but all possible overloadings.How could the compiler decide whether to use
operator<<( ostream &, const std::string & )
or your template? It cannot, so it throws up its hands in despair and gives up. That's what the error is telling you.首先,您需要更仔细地阅读错误消息。作为替代方案,请考虑将语句分解,如下所示:
当您这样做时,您会意识到真正导致问题的原因不是您尝试打印出
getPrice()< /code>,但是您尝试打印出
“价格:”
。出现问题的原因是编译器不知道是使用普通重载来打印字符串,还是使用定义的模板来打印字符串。后者会导致无限递归,并且它实际上无法编译,因为它需要一个可以调用
getPrice
和getCount
的对象来正确编译 - 但它有一个匹配的签名,所以编译器说它不明确,这就是结束。First, you need to read the error message more carefully. As an alternative, consider breaking the statement up, something like this:
When you do, you'll realize that what's really causing the problem is not where you try to print out
getPrice()
, but where you try to print out"Price: "
.The problem is arising because the compiler doesn't know whether to use the normal overload to print out the string, or to use the template being defined to print it out. The latter would cause infinite recursion, and it couldn't actually compile since it requires an object on which you can/could call
getPrice
andgetCount
to compile correctly -- but it has a signature that matches, so the compiler says it's ambiguous, and that's the end of that.错误的原因是您的模板化重载与另一个模板化重载冲突,并且没有理由优先选择一个模板而不是另一个模板:(
ostream
应该是basic_ostream >
。)将重载作为模板的整个想法是有问题的,因为重载显然无法处理除 Record 之外的任何其他类。
可能有一些技术允许您通过一些模板元编程(enable_if 和 Traits)为许多不相关的类似 Record 的类提供单个模板化重载,如果这是想法的话。
The reason of the error is that your templated overload is conflicting with another templated overload, and there is no reason to prefer one template to another:
(
ostream
should be a typedef forbasic_ostream<char, char_traits<char> >
.)The whole idea of making your overload a template is questionable, seeing that the overload clearly cannot handle any other class than your Record.
There probably are techniques to allow you to provide a single templated overload for a number of unrelated Record-like classes with a little template metaprogramming (enable_if and traits), if that is the idea.