我正在尝试制作一个通用容器来容纳对象及其位置:
class Vector;
template <typename T>
class Container
{
public:
void insert(const T& t)
{
insertAtPosition(t.getPosition() ,t);
}
private:
void insertAtPosition(const Vector& v, const T& t);
...
} ;
但是如果用户的对象位置 getter 没有被调用怎么办 getPosition
?
关于容器内部获取项目位置的方式,如何使该容器通用?
到目前为止,我考虑了 3 种方法,但都不是理想的方法:
- 添加
std::function<const Vector& (const T& t)>
Container
的成员.
这是一个干净的 C++ 解决方案,但是这个函数将被非常频繁地调用,它可能会导致明显的性能下降。
向容器中添加一个仿函数对象:
class Vector; template <typename T, typename TGetPosition> class Container { public: Container(TGetPosition getPosition): getPosition_(getPosition){} void insert(const T& t) { insertAtPosition(getPosition_(t) ,t); } private: void insertAtPosition(const Vector& v, const T& t); TGetPosition getPosition_; } ;
我可以使用 object generator idiom使使用 lambdas 成为可能:
template <typename T, typename TGetPosition>
Container<T, TGetPosition> makeContainer(TGetPosition getter)
{
return Container<T, TGetPosition>(getter);
}
...
auto container = makeSimpleContainer<Widget>([](const Widget& w)
{
return w.tellMeWhereYourPositionMightBe();
});
不会有性能开销,但在某些上下文中不可能获取此类容器的类型。例如,您无法创建一个将此类容器作为参数的类,因为 decltype
不会起作用,因为 lambda 不能用于未计算的上下文。
- 使用
#define GETTER getPosition
用户只需更改getPosition
随心所欲。这种方法有太多问题,我什至不知道从哪里开始。
请问还有其他方法吗?我错过了什么吗?欢迎任何指导!
编辑:
关于解决方案 2:我不知道我们如何获得使用 lambda 函数创建的容器类型。一种方法是:
using TContainer = decltype(makeSimpleContainer<Widget>([](const Widget& w)
{
return w.tellMeWhereYourPositionMightBe();
});)
但这行不通,因为 lambda 不能用于未计算的上下文中。
最佳答案
合理可用的选项是期望上下文具有 position_for()
:
template <class T> struct Container {
size_t insert(T const& x) {
insertAtPosition(position_for(x), x);
}
};
Vector const& position_for(const Widget& w) {
return ...;
}
Container<Widget> c;
c.insert(Widget());
...但是容器从业务对象生成 key 的设计通常运行不佳,因为查找对象需要做一个虚拟的,这可能很昂贵。
关于c++ - 如何在不借助 std::function 的情况下存储函数对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34978402/