C++ 动态分配 std::map 比较器
C++ Dynamically assign std::map comparator
所以我有两个 classes 包含 std::map 成员,除了一个映射的顺序是 std::less 而另一个是 std::greater 之外,它们的功能实际上相同。
如果我创建一个抽象父对象 class 并声明一个映射成员,是否有任何方法可以在派生的 class 构造函数中为该成员动态分配比较器?这样,功能显然可以全部驻留在父 class.
中
没有。比较函数用于生成实际的数据结构——更改比较函数需要从头开始重建结构。
也就是说,如果您只想以相反的顺序迭代结构,map
是一个可逆容器,因此您可以使用反向迭代器正常循环结构。
事后无法更改比较器。但是您可以使用相同的比较器 class 并在构建时获得 "greater" 或 "less" 。你只需要一个有状态的比较器:
struct my_compare {
enum compare_type { less, greater };
explicit my_compare(compare_type t) : m_type(t) {}
template<class T, class U>
bool operator()(const T& t, const U& u) const {
if(m_type == less) { return t < u; }
else { return t > u; }
}
compare_type m_type;
};
那你可以做
std::map<int, int, my_compare> less_map((my_compare(my_compare::less)));
std::map<int, int, my_compare> greater_map((my_compare(my_compare::greater)));
多出一对括号是因为it would otherwise be the most vexing parse , even though a function parameter declaration cannot have a qualified name。在 C++11 中,可以改用列表初始化 (my_compare{mycompare::less}
)。
对于您的特定设计,实现可能如下所示
class A {
protected:
explicit A(my_compare::compare_type ct) : my_map(my_compare(ct)) {}
std::map<int, int, my_compare> my_map;
};
class B_less : public A{
public:
B_less() : A(my_compare::less) {}
};
您可以通过创建自定义函子 class 来做您想做的事,该函子根据某些状态使用更少或更多。这是一个例子:
#include <iostream>
#include <string>
#include <map>
struct MyCompare
{
MyCompare(bool useLess) : useLess_(useLess) {}
bool operator()(int lhs, int rhs)
{
if ( useLess_ )
{
return (lhs < rhs);
}
else
{
return (lhs > rhs);
}
}
bool useLess_;
};
int main(int argc, char** argv)
{
std::map<int, std::string, MyCompare> myMap1(MyCompare(true));
std::map<int, std::string, MyCompare> myMap2(MyCompare(false));
myMap1[1] = "abcd";
myMap1[2] = "lmnop";
myMap1[3] = "xyz";
myMap2[1] = "abcd";
myMap2[2] = "lmnop";
myMap2[3] = "xyz";
std::cout << "Map 1: " << std::endl; for ( auto const& v : myMap1 )
{
std::cout << "Key: " << v.first << ", Value: " << v.second << std::endl;
}
std::cout << "Map 2: " << std::endl;
for ( auto const& v : myMap2 )
{
std::cout << "Key: " << v.first << ", Value: " << v.second << std::endl;
}
return 0;
}
输出:
Map 1:
Key: 1, Value: abcd
Key: 2, Value: lmnop
Key: 3, Value: xyz
Map 2:
Key: 3, Value: xyz
Key: 2, Value: lmnop
Key: 1, Value: abcd
在您的情况下,您可以将标志从子 class 传递到父 class,指示使用什么值来创建比较函子。
所以我有两个 classes 包含 std::map 成员,除了一个映射的顺序是 std::less 而另一个是 std::greater 之外,它们的功能实际上相同。
如果我创建一个抽象父对象 class 并声明一个映射成员,是否有任何方法可以在派生的 class 构造函数中为该成员动态分配比较器?这样,功能显然可以全部驻留在父 class.
中没有。比较函数用于生成实际的数据结构——更改比较函数需要从头开始重建结构。
也就是说,如果您只想以相反的顺序迭代结构,map
是一个可逆容器,因此您可以使用反向迭代器正常循环结构。
事后无法更改比较器。但是您可以使用相同的比较器 class 并在构建时获得 "greater" 或 "less" 。你只需要一个有状态的比较器:
struct my_compare {
enum compare_type { less, greater };
explicit my_compare(compare_type t) : m_type(t) {}
template<class T, class U>
bool operator()(const T& t, const U& u) const {
if(m_type == less) { return t < u; }
else { return t > u; }
}
compare_type m_type;
};
那你可以做
std::map<int, int, my_compare> less_map((my_compare(my_compare::less)));
std::map<int, int, my_compare> greater_map((my_compare(my_compare::greater)));
多出一对括号是因为it would otherwise be the most vexing parse , even though a function parameter declaration cannot have a qualified name。在 C++11 中,可以改用列表初始化 (my_compare{mycompare::less}
)。
对于您的特定设计,实现可能如下所示
class A {
protected:
explicit A(my_compare::compare_type ct) : my_map(my_compare(ct)) {}
std::map<int, int, my_compare> my_map;
};
class B_less : public A{
public:
B_less() : A(my_compare::less) {}
};
您可以通过创建自定义函子 class 来做您想做的事,该函子根据某些状态使用更少或更多。这是一个例子:
#include <iostream>
#include <string>
#include <map>
struct MyCompare
{
MyCompare(bool useLess) : useLess_(useLess) {}
bool operator()(int lhs, int rhs)
{
if ( useLess_ )
{
return (lhs < rhs);
}
else
{
return (lhs > rhs);
}
}
bool useLess_;
};
int main(int argc, char** argv)
{
std::map<int, std::string, MyCompare> myMap1(MyCompare(true));
std::map<int, std::string, MyCompare> myMap2(MyCompare(false));
myMap1[1] = "abcd";
myMap1[2] = "lmnop";
myMap1[3] = "xyz";
myMap2[1] = "abcd";
myMap2[2] = "lmnop";
myMap2[3] = "xyz";
std::cout << "Map 1: " << std::endl; for ( auto const& v : myMap1 )
{
std::cout << "Key: " << v.first << ", Value: " << v.second << std::endl;
}
std::cout << "Map 2: " << std::endl;
for ( auto const& v : myMap2 )
{
std::cout << "Key: " << v.first << ", Value: " << v.second << std::endl;
}
return 0;
}
输出:
Map 1: Key: 1, Value: abcd Key: 2, Value: lmnop Key: 3, Value: xyz Map 2: Key: 3, Value: xyz Key: 2, Value: lmnop Key: 1, Value: abcd
在您的情况下,您可以将标志从子 class 传递到父 class,指示使用什么值来创建比较函子。