I have made a boost multiindex of my GameObject, and I am trying to loop through and call non const functions on it. And I cannot for the life of me to get boost to stop giving long nasty compiler errors, like saying there is no matching function call and so forth.
Inside of game.hpp, I have this code to declare what my multiindex container looks like:
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include "game_object.hpp"
struct ByPosition {};
struct ByName {};
namespace bmi = boost::multi_index;
typedef boost::multi_index_container<
GameObject,
bmi::indexed_by<
bmi::random_access<
bmi::tag<ByPosition>
>,
bmi::ordered_non_unique<
bmi::tag<ByName>,
bmi::const_mem_fun<GameObject, const std::string&, &GameObject::name>
>
>
> GameObjectCollection;
class Game
{
//... various other code
private:
GameObjectCollection gameObjects_;
}
then inside game_object.hpp:
#pragma once
#include <string>
#include "drawable.hpp"
class GameObject : public Drawable
{
public:
virtual ~GameObject() = default;
virtual void processEvent(const SDL_Event& event) {}
virtual void update(const float deltaTime) {}
const std::string& name() const { return name_; }
void setName(const std::string& name) { name_ = name; }
private:
std::string name_;
};
then inside game.cpp, where the compiler errors are triggered:
void Game::processEvent(const SDL_Event& event)
{
auto& index = gameObjects_.get<ByPosition>();
for (auto it : index)
index.modify(it, [&event](GameObject& object) {
object.processEvent(event);
});
}
void Game::update()
{
auto& index = gameObjects_.get<ByPosition>();
for (const auto& it : index)
index.modify(it, [&](GameObject& object) {
object.update(deltaTime_);
});
}
And with that boost is giving me these long compiler errors:
game.cpp: In member function ‘void Game::processEvent(const SDL_Event&)’:
game.cpp:68:21: error: no matching function for call to ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::modify(GameObject&, Game::processEvent(const SDL_Event&)::<lambda(GameObject&)>)’
68 | index.modify(it, [&event](GameObject& object) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | object.processEvent(event);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
70 | });
| ~~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: candidate: ‘template<class Modifier> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier) [with Modifier = Modifier; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
472 | bool modify(iterator position,Modifier mod)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: template argument deduction/substitution failed:
game.cpp:68:22: note: cannot convert ‘it’ (type ‘GameObject’) to type ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::iterator’ {aka ‘boost::multi_index::detail::rnd_node_iterator<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::null_augment_policy, boost::multi_index::detail::index_node_base<GameObject, std::allocator<GameObject> > > > >’}
68 | index.modify(it, [&event](GameObject& object) {
| ^~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: candidate: ‘template<class Modifier, class Rollback> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier, Rollback) [with Modifier = Modifier; Rollback = Rollback; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
493 | bool modify(iterator position,Modifier mod,Rollback back_)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: template argument deduction/substitution failed:
game.cpp:68:21: note: candidate expects 3 arguments, 2 provided
68 | index.modify(it, [&event](GameObject& object) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
69 | object.processEvent(event);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~
70 | });
| ~~
game.cpp: In member function ‘void Game::update()’:
game.cpp:78:21: error: no matching function for call to ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::modify(const GameObject&, Game::update()::<lambda(GameObject&)>)’
78 | index.modify(it, [&](GameObject& object) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79 | object.update(deltaTime_);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
80 | });
| ~~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: candidate: ‘template<class Modifier> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier) [with Modifier = Modifier; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
472 | bool modify(iterator position,Modifier mod)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: template argument deduction/substitution failed:
game.cpp:78:22: note: cannot convert ‘it’ (type ‘const GameObject’) to type ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::iterator’ {aka ‘boost::multi_index::detail::rnd_node_iterator<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::null_augment_policy, boost::multi_index::detail::index_node_base<GameObject, std::allocator<GameObject> > > > >’}
78 | index.modify(it, [&](GameObject& object) {
| ^~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: candidate: ‘template<class Modifier, class Rollback> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier, Rollback) [with Modifier = Modifier; Rollback = Rollback; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
493 | bool modify(iterator position,Modifier mod,Rollback back_)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: template argument deduction/substitution failed:
game.cpp:78:21: note: candidate expects 3 arguments, 2 provided
78 | index.modify(it, [&](GameObject& object) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79 | object.update(deltaTime_);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
80 | });
| ~~
To fix it I tried for example:
Noticing that it said that 3 arguments were expected instead of 2, so I checked and apparently you might need a rollback function, eventhough some other documentation seems to suggest that is optional, but I tried it anyway, I didn't have anything to do for a rollback so I tried adding empty lambdas, like this, on update for example:
void Game::update()
{
auto& index = gameObjects_.get<ByPosition>();
for (const auto& it : index)
index.modify(it, [&](GameObject& object) {
object.update(deltaTime_);
}, [](GameObject& obj){});
}
but then it still gives me that same complaint in the compiler error messages, where I see this:
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: template argument deduction/substitution failed:
game.cpp:78:21: note: candidate expects 2 arguments, 3 provided
78 | index.modify(it, [&](GameObject& object) {
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79 | object.update(deltaTime_);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
80 | }, [](GameObject& object) {});
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I also tried to fix it all by using functors instead of lambdas, so in my game.hpp, I added:
class ProcessEvent {
public:
ProcessEvent(const SDL_Event& event) : event_(event) {}
void operator()(GameObject& gameObject) { gameObject.processEvent(event_); }
private:
const SDL_Event& event_;
};
class Update {
public:
Update(const float delta) : delta_(delta) {}
void operator()(GameObject& gameObject) { gameObject.update(delta_); }
private:
const float& delta_;
};
and changed the code in game.cpp to:
void Game::processEvent(const SDL_Event& event)
{
auto& index = gameObjects_.get<ByPosition>();
for (auto it : index)
index.modify(it, ProcessEvent(event));
}
void Game::update()
{
auto& index = gameObjects_.get<ByPosition>();
for (const auto& it : index)
index.modify(it, Update(deltaTime_));
}
but that just gives me these compiler error messages:
game.cpp: In member function ‘void Game::processEvent(const SDL_Event&)’:
game.cpp:68:21: error: no matching function for call to ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::modify(GameObject&, ProcessEvent)’
68 | index.modify(it, ProcessEvent(event));
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: candidate: ‘template<class Modifier> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier) [with Modifier = Modifier; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
472 | bool modify(iterator position,Modifier mod)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: template argument deduction/substitution failed:
game.cpp:68:22: note: cannot convert ‘it’ (type ‘GameObject’) to type ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::iterator’ {aka ‘boost::multi_index::detail::rnd_node_iterator<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::null_augment_policy, boost::multi_index::detail::index_node_base<GameObject, std::allocator<GameObject> > > > >’}
68 | index.modify(it, ProcessEvent(event));
| ^~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: candidate: ‘template<class Modifier, class Rollback> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier, Rollback) [with Modifier = Modifier; Rollback = Rollback; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
493 | bool modify(iterator position,Modifier mod,Rollback back_)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: template argument deduction/substitution failed:
game.cpp:68:21: note: candidate expects 3 arguments, 2 provided
68 | index.modify(it, ProcessEvent(event));
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
game.cpp: In member function ‘void Game::update()’:
game.cpp:76:21: error: no matching function for call to ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::modify(const GameObject&, Update)’
76 | index.modify(it, Update(deltaTime_));
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: candidate: ‘template<class Modifier> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier) [with Modifier = Modifier; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
472 | bool modify(iterator position,Modifier mod)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:472:8: note: template argument deduction/substitution failed:
game.cpp:76:22: note: cannot convert ‘it’ (type ‘const GameObject’) to type ‘boost::multi_index::detail::random_access_index<boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >, boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0> >::iterator’ {aka ‘boost::multi_index::detail::rnd_node_iterator<boost::multi_index::detail::random_access_index_node<boost::multi_index::detail::ordered_index_node<boost::multi_index::detail::null_augment_policy, boost::multi_index::detail::index_node_base<GameObject, std::allocator<GameObject> > > > >’}
76 | index.modify(it, Update(deltaTime_));
| ^~
In file included from game.hpp:6,
from game.cpp:3:
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: candidate: ‘template<class Modifier, class Rollback> bool boost::multi_index::detail::random_access_index<SuperMeta, TagList>::modify(boost::multi_index::detail::random_access_index<SuperMeta, TagList>::iterator, Modifier, Rollback) [with Modifier = Modifier; Rollback = Rollback; SuperMeta = boost::multi_index::detail::nth_layer<1, GameObject, boost::multi_index::indexed_by<boost::multi_index::random_access<boost::multi_index::tag<ByPosition> >, boost::multi_index::ordered_non_unique<boost::multi_index::tag<ByName>, boost::multi_index::const_mem_fun<GameObject, const std::__cxx11::basic_string<char>&, &GameObject::name> > >, std::allocator<GameObject> >; TagList = boost::mpl::v_item<ByPosition, boost::mpl::vector0<mpl_::na>, 0>]’
493 | bool modify(iterator position,Modifier mod,Rollback back_)
| ^~~~~~
/usr/include/boost/multi_index/random_access_index.hpp:493:8: note: template argument deduction/substitution failed:
game.cpp:76:21: note: candidate expects 3 arguments, 2 provided
76 | index.modify(it, Update(deltaTime_));
| ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
I have been struggling trying to figure this all out for hours now.
Hopefully someone here can help me out with this.
Thank you.
for (auto it : index)is the problem modify expects an iterator as first argument not a value (currentlyitis a copy of a value in index, NOT an iterator over index). You will need a for loop using explicit iterators. E.g. useindex.begin()toindex.end()GameObjectan alias forint. 4) Don't introduce a class,Game, whose only purpose is to house the problematic code. A free function would do just as well. 5) One error at a time. This would cut your line count in half: wandbox.org/permlink/QIfNma3firkYd9eC