2

suppose I have a table:

struct [[eosio::table]] _stuff {
    symbol curr;
    // other stuff
    uint64_t primary_key() const { return curr.code().raw(); }
};

typedef eosio::multi_index<name("stuff"), _stuff> stuff;

which I want to iterate through, passing the iterator to a function for encapsulation of business logic:

stuff st(_self, _self.value);
for (auto &o : st) {
   do_biz_stuff(o);
}

how do I declare the function? I need an iterator but cannot declare it as auto:

void do_biz_stuff(auto o) { ... }

as the compiler pukes with:

error: 'auto' not allowed in function prototype

and trying the standard iterator requires a "template arguments":

void do_biz_stuff(std::iterator o) { ... }

here's the actual error:

use of class template 'iterator' requires template arguments; argument deduction not allowed in function prototype

what is the correct incantation I need to issue to make this work?

1 Answer 1

5

I had the same question and ended up figuring it out by reading the multi_index.hpp from eosio.cdt code and wanted to share my solution.

Instead of using auto, declare the type by using myindex::const_iterator:

struct [[eosio::table]] _obj {
    name key;
    uint64_t primary_key() const { return key.value; }
};

typedef eosio::multi_index<name("myindex"), _obj> myindex;

void do_biz_stuff(myindex::const_iterator& o) { ... }

Additional Note

If you want to use modify, erase, or iterator_to inside do_biz_stuff you must be sure to pass the iterator by reference and also to pass the multi_index instance by reference. Otherwise you'll receive the errors like object passed to modify / erase / iterator_to is not in multi_index or copy constructor of 'item_ptr' is implicitly deleted because field '_item' has a deleted copy constructor

void do_biz_stuff(myindex& idx, myindex::const_iterator& itr) {
    idx.erase(itr);
}

Using with Secondary Index

Also I just ran into the usecase of using with secondary index.

Define template to pass types:

struct [[eosio::table]] _obj {
    name key;
    name secondary;
    uint64_t primary_key() const { return key.value; }
    uint64_t mysecondary() const { return secondary.value; }
};

typedef eosio::multi_index<
   name("myindex"), 
   _obj,
   indexed_by<name("mysecondary"), const_mem_fun<_obj, uint64_t, &_obj::mysecondary>>
> myindex;

template <typename idxT, typename itrT>
void do_biz_stuff(idxT& idx, itrT& itr) { ... }

Usage:

myindex myidx(_self, _self.value);
auto mySecIdx = myidx.get_index<name("mysecondary")>();
auto mySecItr = mySecIdx.lower_bound(name("testSecondaryKey"));

do_biz_stuff<decltype(mySecIdx), decltype(mySecItr)>(mySecIdx, mySecItr);
1
  • "figuring it out by reading the multi_index.hpp" -- I tried the same but it's just above my paygrade. haha
    – ekkis
    Commented Oct 29, 2019 at 21:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.