我对运营商的实施<对于长值数组的包装类,重载不能正常工作。
在std :: map中使用此包装类作为Key时,如果我混合不同长度的数组,则调用/ find中的函数不起作用。
const oid oid1[] = { 1,3,6,1,4,1,42570,1,3,1 };
oid_wrapper wrapper1(oid1, 10);
const oid oid2[] = { 1,3,6,1,4,1,42570,1,3,1,9,1 };
oid_wrapper wrapper1(oid2, 12);
首先添加wrapper1然后再将wrapper2添加到地图中,它总是会找到带有at / find的wrapper1,但是对于wrapper2,它会使用at和iterator.end以及find抛出out_of_range异常。
当首先添加wrapper2然后再将wrapper1添加到地图时,它总会找到带有at / find的wrapper2,但是对于wrapper1,它会使用at和iterator.end以及find抛出out_of_range异常。
oid类型来自Net-SNMP,实际上是一个unsigned long int
那么我的实现缺失或完全错误是什么?
#include <ostream>
#include <sstream>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
class oid_wrapper {
public:
oid_wrapper(const oid* _oid_value, int _oid_length) : oid_value(0), oid_length (_oid_length) {
oid_value = snmp_duplicate_objid(_oid_value, oid_length);
}
const oid* get_oid() const { return oid_value; }
const int& get_length() const { return oid_length; }
/**
* copy operator overloader
*/
oid_wrapper& operator=(const oid_wrapper& wrapper) {
oid_value = snmp_duplicate_objid(wrapper.get_oid(), wrapper.get_length());
oid_length = wrapper.get_length();
return *this;
}
/**
* equal operator overloader
*/
bool operator==(const oid_wrapper& rhs) const {
const oid* rhs_oid = rhs.get_oid();
const int rhs_length = rhs.get_length();
if (netsnmp_oid_equals(oid_value, oid_length, rhs_oid, rhs_length) == 0) {
return true;
} else {
return false;
}
}
/**
* less-than operator overloader
*/
bool operator<(const oid_wrapper& rhs) const {
const oid* rhs_oid = rhs.get_oid();
const int rhs_length = rhs.get_length();
if (oid_length < rhs_length) { return true; }
for (int i = 0; i < oid_length; i++) {
if (oid_value[i] < rhs_oid[i]) { return true; }
}
return false;
}
const long getLastNumberInOid() const { return oid_value[oid_length - 1]; }
bool operator!=(const oid_wrapper& rhs) { return !operator==(rhs); }
bool operator>(const oid_wrapper& rhs) { return !operator<(rhs); }
bool operator<=(const oid_wrapper& rhs) { return !operator>(rhs); }
bool operator>=(const oid_wrapper& rhs) { return !operator<(rhs); }
private:
const oid* oid_value;
int oid_length;
};
这是我的测试类,我的目的是检查它是否有效:
#include <iostream>
#include <ostream>
#include <string>
#include <map>
#include <stdexcept>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include "oid_wrapper.h"
using namespace std;
int main(int argc, char **argv) {
cout << "Testing first set of OID" << endl;
const oid oid1[] = { 1,3,6,1,4,1,40850,1,3 };
const oid_wrapper parent1 (oid1, 9);
const oid_wrapper parent1_child1 (parent1, 40);
const oid_wrapper parent1_child2 (parent1, 41);
const oid_wrapper parent1_child3 (parent1, 42);
const oid_wrapper parent1_child4 (parent1, 43);
map<oid_wrapper, string> test;
test.insert(make_pair(parent1_child1, "parent1_child1"));
test.insert(make_pair(parent1_child2, "parent1_child2"));
test.insert(make_pair(parent1_child3, "parent1_child3"));
test.insert(make_pair(parent1_child4, "parent1_child4"));
if (test.size() != 4) { cout << "FAIL" << endl; }
cout << "Number of OID in list: " << test.size() << endl;
const oid_wrapper parent11 (oid1, 9);
const oid_wrapper parent1_child11 (parent11, 40);
try {
string teststring = test.at(parent1_child11);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child12 (parent11, 41);
try {
string teststring = test.at(parent1_child12);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child13 (parent11, 42);
try {
string teststring = test.at(parent1_child13);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child14 (parent11, 43);
try {
string teststring = test.at(parent1_child14);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
cout << "Testing second set of OID" << endl;
const oid oid2[] = { 1,3,6,1,4,1,40850,2,1,9,1 };
const oid_wrapper parent2 (oid2, 11);
const oid_wrapper parent2_child1 (parent2, 1);
const oid_wrapper parent2_child2 (parent2, 2);
const oid_wrapper parent2_child3 (parent2, 3);
const oid_wrapper parent2_child4 (parent2, 4);
test.insert(make_pair(parent2_child1, "parent2_child1"));
test.insert(make_pair(parent2_child2, "parent2_child2"));
test.insert(make_pair(parent2_child3, "parent2_child3"));
test.insert(make_pair(parent2_child4, "parent2_child4"));
if (test.size() != 8) { cout << "FAIL" << endl; }
cout << "Number of OID in list: " << test.size() << endl;
const oid_wrapper parent21 (oid2, 11);
const oid_wrapper parent1_child21 (parent21, 1);
try {
string teststring = test.at(parent1_child21);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child22 (parent21, 2);
try {
string teststring = test.at(parent1_child22);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child23 (parent21, 3);
try {
string teststring = test.at(parent1_child23);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
const oid_wrapper parent1_child24 (parent21, 4);
try {
string teststring = test.at(parent1_child24);
cout << "Success" << endl;
} catch (out_of_range& e) {
cout << "Failure" << endl;
}
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,1,9,1 };
const oid_wrapper wrapper(newoid, 11, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run1 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,1,9,1 };
const oid_wrapper wrapper(newoid, 11, i);
try {
string teststring = test.at(wrapper);
run1++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run1 == 100) { cout << "Run 1 Success" << endl; }
else { cout << "Run 1: " << run1 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,1,3 };
const oid_wrapper wrapper(newoid, 9, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run2 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,1,3 };
const oid_wrapper wrapper(newoid, 9, i);
try {
string teststring = test.at(wrapper);
run2++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run2 == 100) { cout << "Run 2 Success" << endl; }
else { cout << "Run 2: " << run2 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 10; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2 };
const oid_wrapper wrapper(newoid, 8, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run3 = 0;
for (int i = 0; i < 10; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2 };
const oid_wrapper wrapper(newoid, 8, i);
try {
string teststring = test.at(wrapper);
run3++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run3 == 10) { cout << "Run 3 Success" << endl; }
else { cout << "Run 3: " << run3 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,2,5,1 };
const oid_wrapper wrapper(newoid, 11, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run4 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,2,5,1 };
const oid_wrapper wrapper(newoid, 11, i);
try {
string teststring = test.at(wrapper);
run4++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run4 == 100) { cout << "Run 4 Success" << endl; }
else { cout << "Run 4: " << run4 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,3,5,2 };
const oid_wrapper wrapper(newoid, 11, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run5 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,3,5,2 };
const oid_wrapper wrapper(newoid, 11, i);
try {
string teststring = test.at(wrapper);
run5++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run5 == 100) { cout << "Run 5 Success" << endl; }
else { cout << "Run 5: " << run5 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,2,5,2 };
const oid_wrapper wrapper(newoid, 10, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run6 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,2,5,2 };
const oid_wrapper wrapper(newoid, 10, i);
try {
string teststring = test.at(wrapper);
run6++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run6 == 100) { cout << "Run 6 Success" << endl; }
else { cout << "Run 6: " << run6 << endl; }
//#################################################
//Adding 100 OIDs
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,5,2,3,5 };
const oid_wrapper wrapper(newoid, 12, i);
test.insert(make_pair(wrapper, "wrapper"));
}
//Query for the 100 added OIDs
int run7 = 0;
for (int i = 0; i < 100; i++) {
const oid newoid[] = { 1,3,6,1,4,1,40850,2,5,2,3,5 };
const oid_wrapper wrapper(newoid, 12, i);
try {
string teststring = test.at(wrapper);
run7++;
} catch (out_of_range& e) {
//FAIL
}
}
if (run7 == 100) { cout << "Run 7 Success" << endl; }
else { cout << "Run 7: " << run7 << endl; }
}
答案 0 :(得分:1)
问题可能是您的operator<
不是反对称的。想象一下这段代码:
const oid oid1[] = {5};
oid_wrapper wrapper1(oid1, 1);
const oid oid2[] = {1, 4};
oid_wrapper wrapper2(oid2, 2);
bool b1 = wrapper1 < wrapper2;
bool b2 = wrapper2 < wrapper1;
b1
为true
,因为wrapper1
的长度小于wrapper2
的长度。
b2
也是true
,因为wrapper2
中的第一个oid小于wrapper1
中的第一个oid。
您必须确保operator<
是总排序。如果false
,则应返回oid_length > rhs_length
。
此外,您无法将operator>
实现为! <
,因为这不适用于相等的值。运营商的最佳选择是实施operator==
和operator<
并将其余部分表示为(伪代码):
operator!=(a, b) {! (a == b)}
operator<=(a, b) {a < b || a == b}
operator>(a, b) {! (a < b)}
operator>=(a, b) {! (a < b)}
答案 1 :(得分:0)
我使用net-snmp函数snmp_oid_compare而不是实现我自己的比较。这解决了这个问题。
#ifndef OID_WRAPPER_H_
#define OID_WRAPPER_H_
#include <stdio.h>
#include <stdlib.h>
#include <ostream>
#include <sstream>
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
class oid_wrapper {
friend std::ostream& operator<<(std::ostream& output, const oid_wrapper& wrapper);
public:
oid_wrapper(const oid* _oid_value, unsigned long _oid_length) : oid_value(0), oid_length(_oid_length) {
oid_value = snmp_duplicate_objid(_oid_value, oid_length);
}
const oid* get_oid() const { return oid_value; }
const unsigned long& get_length() const { return oid_length; }
int compare(const oid_wrapper& rhs) const {
return snmp_oid_compare(oid_value, oid_length, rhs.oid_value, rhs.oid_length);
}
void print(std::ostream &out) const {
for(unsigned long i = 0; i < oid_length; i++) {
if (i != 0) { out << "."; }
out << oid_value[i];
}
}
/**
* copy operator overload
*/
oid_wrapper& operator=(const oid_wrapper& wrapper) {
if (oid_value != 0) { free(oid_value); }
oid_value = snmp_duplicate_objid(wrapper.oid_value, wrapper.oid_length);
oid_length = wrapper.oid_length;
return *this;
}
/**
* assignment operator overload
*/
oid operator[](unsigned long i) {
return (i < oid_length) ? oid_value[i] : oid();
}
bool operator==(const oid_wrapper& rhs) const { return compare(rhs)==0; }
bool operator!=(const oid_wrapper& rhs) const { return compare(rhs)!=0; }
bool operator<(const oid_wrapper& rhs) const { return compare(rhs)<0; }
bool operator>(const oid_wrapper& rhs) const { return compare(rhs)>0; }
bool operator<=(const oid_wrapper& rhs) const { return compare(rhs)<=0; }
bool operator>=(const oid_wrapper& rhs) const { return compare(rhs)>=0; }
private:
oid* oid_value;
unsigned long oid_length;
};
/**
* output operator overloader
*/
inline std::ostream& operator<<(std::ostream& output, const oid_wrapper& wrapper) {
wrapper.print(output);
return output;
}
#endif /* OID_WRAPPER_H_ */
函数snmp_oid_compare的代码。这可以用于任何需要比较long数组的实现。
int snmp_oid_compare(const oid * in_name1, size_t len1,
const oid * in_name2, size_t len2)
{
register int len;
register const oid *name1 = in_name1;
register const oid *name2 = in_name2;
/*
* len = minimum of len1 and len2
*/
if (len1 < len2) { len = len1; }
else { len = len2; }
/*
* find first non-matching OID
*/
while (len-- > 0) {
/*
* these must be done in seperate comparisons, since
* subtracting them and using that result has problems with
* subids > 2^31.
*/
if (*(name1) != *(name2)) {
if (*(name1) < *(name2)) { return -1; }
return 1;
}
name1++;
name2++;
}
/*
* both OIDs equal up to length of shorter OID
*/
if (len1 < len2) return -1;
if (len2 < len1) return 1;
return 0;
}