c++ - How to store a function object without resorting to std::function?

问题描述:

I am trying to make a generic container that would hold objects and their position:

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);

...

} ;

But what if the users' object position getter is not called getPosition?

How can I make this container generic with respect to the way in which the container internally obtains the position of an item?

So far, I have considered 3 approaches, none of them ideal:

Add a std::function<const Vector& (const T& t)> member to the Container.

This is a clean C++ solution, but this function is going to be called very very often and it may result in noticeable performance decrease.

Add a functor object to the container:

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_;

} ;

I can use the object generator idiom to make it possible to use 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();

});

There would be no performance overhead, but it would be impossible to get the type of such a container in certain contexts. For example, you could not create a class that would take such a container as a parameter, since decltype would not work, because lambdas cannot be used in unevaluated contexts.

Use #define GETTER getPosition and the user would just change getPosition to whatever he likes. There are so many things wrong with this approach that I don't even know where to start.

Please, is there some other way to do this? Did I miss anything. Any guidance is most welcome!

EDIT:

Regarding solution 2: I have no idea how could we get a the type of a container created with a lambda function. One way would be: