我正在尝试创建一个容纳对象及其位置的通用容器:
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);
...
} ;
但是,如果用户的对象位置获取器未被调用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
不起作用,因为lambdas不能在未评估的上下文中使用。
#define GETTER getPosition
,用户只需将getPosition
更改为他喜欢的内容即可。这种方法有很多问题,我甚至不知道从哪里开始。拜托,还有其他方法吗?我错过了什么。欢迎任何指导!
编辑:
关于解决方案2:我不知道如何获得使用lambda函数创建的容器类型。一种方法是:
using TContainer = decltype(makeSimpleContainer<Widget>([](const Widget& w)
{
return w.tellMeWhereYourPositionMightBe();
});)
但是这不起作用,因为lambdas不能用于未评估的上下文中。
答案 0 :(得分:1)
合理可用的选项是期望上下文具有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());
...但是容器从业务对象生成密钥的设计通常不能很好地进行,因为查找虚拟对象需要进行操作,这可能很昂贵。
答案 1 :(得分:1)
即使您需要创建一个容纳容器的类,您的第二个解决方案似乎仍然有效:
template <typename Container>
struct SomeClass {
SomeClass(const Container &container) : container(container) { }
Container container;
};
int main()
{
auto container = makeSimpleContainer<Widget>([](const Widget& w)
{
return w.tellMeWhereYourPositionMightBe();
});
SomeClass<decltype(container)> test(container);
}