草稿
struct NoCaseCompare : public std::binary_function<std::string, std::string, bool>
{
static bool cmp(char c1, char c2)
{
return toupper(c1) < toupper(c2);
}
bool operator()(const std::string& s1, const std::string& s2) const
{
return lexicographical_compare(s1.begin(), s1.end(), s2.begin(), s2.end(), cmp);
}
};
typedef std::map<std::string, SipMessage::MethodType, NoCaseCompare> MethodTypeMap_t;
typedef std::map<SipMessage::MethodType, std::string> MethodStringMap_t;
1. std::map 的第三个参数?
Functor defined: any class that overloads operator()
Also called “function objects” because these objects can be called like functions – they can take arguments and return a value
Functors that return bool are called “predicates”
作为map的key必须实现“<”操作符,std::string 有默认的实现,但是是区分大小写的, 比如 “aaB”, "BYE", "ABC", 默认排序结果:
“ABC”
“BYE”
"aaB"
如果要实现如下的排序结果:
“aaB”
"ABC"
“BYE”
这就要自己来定义functor了
2. NoCaseCompare 为什么要继承 std::binary_function
如果不使用std::bind1st, std::bind2nd, 那么在这里继承 std::binary_function没有“实际”的意义,只是一种typedef,那么这种typedef主要目的是增加代码的可读性:
- 明确的标示出 NoCaseCompare是一个functor
- 强制规定了NoCaseCompare在重载操作符()的时候必须接受两个参数,并且强制规定了两个参数的类型和返回类型
3. operator() 后面为什么要加const?
4. NoCaseCompare 为什么要声明为struct?
从语法上,在C++中(只讨论C++中)。class和struct做类型定义时只有两点区别:
(一)默认继承权限。如果不明确指定,来自class的继承按照private继承处理,来自struct的继承按照public继承处理;
(二)成员的默认访问权限。class的成员默认是private权限,struct默认是public权限。
除了这两点,class和struct基本就是一个东西。语法上没有任何其它区别。
那这里的申明应该仅仅只是编程风格的考虑,那么这种编程风格是什么?
5. cmp函数为什么要声明为static
lexicographical_compare 这里需要的是一个函数指针
static函数实际上就是一个普通函数,只是逻辑上属于类,并可以访问类的静态成员,函数名就是指向函数地址的指针
而普通成员函数显然不能在这里被传入的,只有类的实例才能调用类的成员函数
struct HeaderIterator : public std::iterator<std::input_iterator_tag, std::string> { public: HeaderIterator() : mStr(0), mSize(0), mStart(0), mEnd(0) { } HeaderIterator(const std::string &str) : mStr(&str), mSize(mStr->size()), mStart(0), mEnd(mStr->find(CrLf)) { } HeaderIterator(const HeaderIterator& copy) : mStr(copy.mStr), mSize(copy.mSize), mStart(copy.mStart), mEnd(copy.mEnd) { } HeaderIterator& operator++() { FindNext(); return *this; } HeaderIterator operator++(int) { HeaderIterator temp(*this); ++(*this); return temp; } std::string operator*() const { return std::string(*mStr, mStart, mEnd - mStart); } bool operator==(const HeaderIterator& rhs) const { return (rhs.mStr == mStr && rhs.mStart == mStart && rhs.mEnd == mEnd); } bool operator!=(const HeaderIterator& rhs) const { return !(rhs == *this); } const std::string::size_type Pos(void) const { return mStart; } private: void FindNext(void) { if (mEnd == std::string::npos || ((mSize - mEnd) <= CrLf.size())) { mStr = 0; mStart = mEnd = 0; return; } mStart = mEnd + CrLf.size(); mEnd = mStr->find(CrLf, mStart); } const std::string *mStr; const std::string::size_type mSize; std::string::size_type mStart; std::string::size_type mEnd; };
// Test IPv4 addresses SdpMessage sdp; sdp.sessionId = 1; sdp.timestamp = 2; sdp.addrType = SdpMessage::SDP_ADDR_TYPE_IPV4; sdp.addrStr = "1.2.3.4"; sdp.transportPort = 50050; sdp.mediaFormat = SdpMessage::SDP_MEDIA_FORMAT_PCMU; const std::string expMsgIpv4 = "v=0\r\n" "o=- 1 2 IN IP4 1.2.3.4\r\n" "s=Spirent TestCenter\r\n" "c=IN IP4 1.2.3.4\r\n" "t=2 0\r\n" "m=audio 50050 RTP/AVP 0 100\r\n" "a=rtpmap:0 PCMU/8000\r\n" "a=rtpmap:100 telephone-event/8000\r\n" "a=ptime:20\r\n" "a=fmtp:100 0-15\r\n"; CPPUNIT_ASSERT(SipProtocol::BuildSdpString(sdp) == expMsgIpv4);