【C++Primer求助】multiset容器的自定义比较函数问题

albb318 2009-02-07 03:55:03

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <cmath>

#ifndef MYHEAD_H
#define MYHEAD_H

using namespace std;

class Base
{
private:
string Isbn;
protected:
double Price;
public:
virtual double GetPrice(size_t Num) const
{
return Price*Num;
}
const string &GetName() const
{
return Isbn;
}
Base(string isbn="",double price=0):Isbn(Isbn),Price(price){};
virtual Base *Clone() const
{
return new Base(*this);
}
virtual ~Base(){};
};

class Bulk:public Base
{
private:
double Discount;
size_t Limit;
public:
double GetPrice(size_t Num) const
{
return Num>=Limit?(Base::GetPrice(Num)*Discount):(Base::GetPrice(Num));
}
Bulk(string isbn="",double price=0,double discount=0,size_t limit=0)
:Base(isbn,price),Discount(discount),Limit(limit){};
Bulk *Clone() const
{
return new Bulk(*this);
}
};

class Sales_item
{
private:
Base *BaseP;
size_t* Use;
public:
Sales_item(const Base &org):BaseP(org.Clone()),Use(new size_t(1)){};
Sales_item(const Sales_item &org):BaseP(org.BaseP),Use(org.Use){++*Use;};
Base *operator->() const
{
return BaseP;
}
Base &operator*() const
{
return *BaseP;
}
Sales_item &operator=(const Sales_item &right)
{
++*(right.Use);
this->~Sales_item();
BaseP=right.BaseP;
Use=right.Use;
}

~Sales_item()
{
if(--*Use==0)
{
delete BaseP;
delete Use;
}
}

};

inline bool compare(const Sales_item &left,const Sales_item &right)
{
return (left->GetName())<(right->GetName());
}

typedef bool (*Comp)(const Sales_item &left,const Sales_item &right);
typedef multiset<Sales_item,Comp> Items;


class Basket
{
private:
multiset<Sales_item,Comp> BookList;;
public:
Basket():BookList(compare){};
void AddOne(const Sales_item &item)
{
BookList.insert(item);
}
double GetPrice()
{
double Price=0;
for(Items::const_iterator Scan=BookList.begin();
Scan!=BookList.end();
Scan=upper_bound(BookList.begin(),BookList.end(),*Scan))
Price+=(*Scan)->GetPrice(count(BookList.begin(),BookList.end(),*Scan));
return Price;
}
};

#endif


C++Primer的习题,自定义了Base基类,Bulk打折派生类,用Sales_itme类句柄进行管理。
定义multiset保存句柄,但是定义比较函数时出问题了,如下:
>------ 已启动生成: 项目: Death from Above, 配置: Debug Win32 ------
1>正在编译...
1>Death from Above.cpp
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)”: 无法从“Sales_item”为“const std::_Tree<_Traits> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\xtree(1453) : 参见“std::operator ==”的声明
1> d:\program files\microsoft visual studio 9.0\vc\include\algorithm(162): 参见对正在编译的函数 模板 实例化“__w64 int std::_Count<std::_Tree<_Traits>::iterator,_Ty>(_InIt,_InIt,const _Ty &)”的引用
1> with
1> [
1> _Traits=std::_Tset_traits<Sales_item,Comp ,std::allocator<Sales_item>,true>,
1> _Ty=Sales_item,
1> _InIt=std::_Tree<std::_Tset_traits<Sales_item,Comp ,std::allocator<Sales_item>,true>>::iterator
1> ]
1> f:\课程\c\death from above\death from above\death from above\myhead.h(113): 参见对正在编译的函数 模板 实例化“__w64 int std::count<std::_Tree<_Traits>::iterator,Sales_item>(_InIt,_InIt,const _Ty &)”的引用
1> with
1> [
1> _Traits=std::_Tset_traits<Sales_item,Comp ,std::allocator<Sales_item>,true>,
1> _InIt=std::_Tree<std::_Tset_traits<Sales_item,Comp ,std::allocator<Sales_item>,true>>::iterator,
1> _Ty=Sales_item
1> ]
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)”: 无法从“Sales_item”为“const std::basic_string<_Elem,_Traits,_Alloc> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\string(90) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)”: 无法从“Sales_item”为“const _Elem *”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\string(80) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)”: 无法从“Sales_item”为“const std::basic_string<_Elem,_Traits,_Alloc> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\string(70) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)”: 无法从“Sales_item”为“const std::vector<_Ty,_Alloc> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\vector(1303) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::istream_iterator<_Ty,_Elem,_Traits,_Diff> &,const std::istream_iterator<_Ty,_Elem,_Traits,_Diff> &)”: 无法从“Sales_item”为“const std::istream_iterator<_Ty,_Elem,_Traits,_Diff> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\iterator(266) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::istreambuf_iterator<_Elem,_Traits> &,const std::istreambuf_iterator<_Elem,_Traits> &)”: 无法从“Sales_item”为“const std::istreambuf_iterator<_Elem,_Traits> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\streambuf(548) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::allocator<_Ty> &,const std::allocator<_Other> &) throw()”: 无法从“Sales_item”为“const std::allocator<_Ty> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\xmemory(173) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)”: 无法从“Sales_item”为“const std::reverse_iterator<_RanIt> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\xutility(2220) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)”: 无法从“Sales_item”为“const std::_Revranit<_RanIt,_Base> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\xutility(2024) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2784: “bool std::operator ==(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)”: 无法从“Sales_item”为“const std::pair<_Ty1,_Ty2> &”推导 模板 参数
1> d:\program files\microsoft visual studio 9.0\vc\include\utility(68) : 参见“std::operator ==”的声明
1>d:\program files\microsoft visual studio 9.0\vc\include\algorithm(152) : error C2676: 二进制“==”: “Sales_item”不定义该运算符或到预定义运算符可接收的类型的转换
1>生成日志保存在“file://f:\课程\C\Death From Above\Death from Above\Death from Above\Debug\BuildLog.htm”
1>Death from Above - 12 个错误,0 个警告
========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========


好像是缺少“==”的定义,但明明已经有compare函数了啊。。。
求大虾帮助~~
...全文
602 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2010-01-06
  • 打赏
  • 举报
回复
试multiset就不要把其它代码带进来干扰视线。
WEBCONFIG 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 nineforever 的回复:]
compare是函数,multiset的模板参数要求的是类型
你需要在multiset的模板参数里指定比较函数的类型,同时在multiset的构造函数里提供比较函数本身
[/Quote]
正解啊
nineforever 2009-02-07
  • 打赏
  • 举报
回复
compare是函数,multiset的模板参数要求的是类型
你需要在multiset的模板参数里指定比较函数的类型,同时在multiset的构造函数里提供比较函数本身
albb318 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 nineforever 的回复:]
你的Sales_item需要提供operator==,因为count会用到
另外你需要传递compare给upper_bound,因为它默认用operator <
[/Quote]
再次修改

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <cmath>

#ifndef MYHEAD_H
#define MYHEAD_H

using namespace std;

class Base//定义基类
{
private:
string Isbn;
protected:
double Price;
public:
virtual double GetPrice(size_t Num) const
{
return Price*Num;
}
string GetName() const
{
return Isbn;
}
Base(string isbn="",double price=0):Isbn(Isbn),Price(price){};
virtual Base *Clone() const
{
return new Base(*this);
}
virtual ~Base(){};
};

class Bulk:public Base//打折类
{
private:
double Discount;
size_t Limit;
public:
double GetPrice(size_t Num) const
{
return Num>=Limit?(Base::GetPrice(Num)*Discount):(Base::GetPrice(Num));
}
Bulk(string isbn="",double price=0,double discount=0,size_t limit=0)
:Base(isbn,price),Discount(discount),Limit(limit){};
Bulk *Clone() const
{
return new Bulk(*this);
}
};

class Sales_item//句柄类
{
private:
Base *BaseP;
size_t* Use;
public:
Sales_item():BaseP(0),Use(new size_t(1)){}
Sales_item(const Base &org):BaseP(org.Clone()),Use(new size_t(1)){};
Sales_item(const Sales_item &org):BaseP(org.BaseP),Use(org.Use){++*Use;};
Base *operator->() const
{
return BaseP;
}
Base &operator*() const
{
return *BaseP;
}
Sales_item &operator=(const Sales_item &right)
{
++*(right.Use);
this->~Sales_item();
BaseP=right.BaseP;
Use=right.Use;
}

~Sales_item()
{
if(--*Use==0)
{
delete BaseP;
delete Use;
}
}

};


bool operator<(const Sales_item &left,const Sales_item &right)
{
return (left->GetName())<(right->GetName());
}//定义符号"<"

bool compare(const Sales_item &left,const Sales_item &right)
{
return (left->GetName())<(right->GetName());
}//定义一个比较函数

class Compare
{
public:
bool operator()(const Sales_item &left,const Sales_item &right)
{
return (left->GetName())<(right->GetName());
}
};//定义一个函数对象进行比较




class Basket
{
//typedef bool (*Comp)(const Sales_item &left,const Sales_item &right);
typedef multiset<Sales_item,Compare> Items;//这里有个问题:
//typedef multiset<Sales_item,Compare> Items; OK
//typedef multiset<Sales_item> Items; OK
//typedef multiset<Sales_item,compare> Items; Error
//提示说“compare”不是参数“_Pr”的有效 模板 类型变量
//为什么直接把compare函数传给multiset就出错呢?
public:
Basket(){};
void AddOne(const Sales_item &item)
{
BookList.insert(item);
}
double GetPrice()
{
double Price=0;
for(Items::const_iterator Scan=BookList.begin();
Scan!=BookList.end();
Scan=upper_bound(BookList.begin(),BookList.end(),*Scan))
Price+=(*Scan)->GetPrice(BookList.count(*Scan));
return Price;
}
private:
Items BookList;
};

nineforever 2009-02-07
  • 打赏
  • 举报
回复
你的Sales_item需要提供operator==,因为count会用到
另外你需要传递compare给upper_bound,因为它默认用operator<
albb318 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 nineforever 的回复:]
count需要operator==
[/Quote]
改成这样了,可还是不行。

class Basket
{
typedef bool (*Comp)(const Sales_item &left,const Sales_item &right);
typedef multiset<Sales_item,Comp> Items;
public:
Basket():BookList(compare){};
void AddOne(const Sales_item &item)
{
BookList.insert(item);
}
double GetPrice()
{
double Price=0;
for(Items::const_iterator Scan=BookList.begin();
Scan!=BookList.end();
Scan=upper_bound(BookList.begin(),BookList.end(),*Scan))
Price+=(*Scan)->GetPrice(BookList.count(*Scan));
return Price;
}
private:
multiset<Sales_item,Comp> BookList;
};
waizqfor 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 albb318 的帖子:]

#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <cmath>

#ifndef MYHEAD_H
#define MYHEAD_H

using namespace std;

class Base
{
private:
string Isbn;
protected:
double Price;
public:
virtual double GetPrice(size_t Num) const
{
return Price*Num;
}
const string &GetName() const
{
return Isbn;
}
Base(string isbn="",do…
[/Quote]
重载的问题
nineforever 2009-02-07
  • 打赏
  • 举报
回复
count需要operator==

65,211

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧