0

This is more a C++ question than EOS contracts question but I am having trouble creating a template function for migrating tables to a different scope. I cannot get this to compile.

template <typename T, typename E, typename F>
void migrate_table(name code, uint16_t batch_size, name source_scope, name destn_scope, void (*mapper)(E&, F&) ) {
    T source(code, source_scope.value);
    T destination(code, destn_scope.value);
    auto lastdest = destination.end();
    if (lastdest == destination.begin()) {
        return; // empty table nothing copy
    }
    uint64_t src_primary_key = (--lastdest)->primary_key();

    auto source_itrr = source.find(src_primary_key);
    source_itrr++;
    uint16_t batch_counter = 0;

    while (batch_counter < batch_size && source_itrr != source.end()) {
        destination.emplace(code, [&](E &e){
            mapper(e, source_itrr);
        });
        ++source_itrr;
        ++batch_counter;
    }
} 

when I am trying to call the function like this:

    migrate_table<regmembers>(get_self(), batch_size, get_self(), NEW_SCOPE, [](member& dest, member& src){
            dest.sender = src.sender;
            dest.agreedtermsversion = src.agreedtermsversion;
        });

The compilation error I get is:

no matching function for call to 'migrate_table' migrate_table(get_self(), batch_size, get_self(), NEW_SCOPE, [](member& dest, member& src){ ^~~~~~~~~~~~~~~~~~~~~~~~~ ... candidate template ignored: could not match 'void (*)(E &, F &)' against '(lambda at

void migrate_table(name code, uint16_t batch_size, name source_scope, name destn_scope, void (*mapper)(E&, F&) ) {

I am guessing is something about the way I am passing the parameter as a reference and it being a template type but I cannot get it to work. I could avoid the template aspect all together but I have quite a few tables to migrate so would like to avoid the duplicate code.

1 Answer 1

1
template <typename T, typename Lambda>
void migrate_table(name code, uint16_t batch_size, name source_scope, name destn_scope, Lambda&& mapper) {
    T source(code, source_scope.value);
    T destination(code, destn_scope.value);
    auto lastdest = destination.end();
    if (lastdest == destination.begin()) {
        return; // empty table nothing copy
    }
    uint64_t src_primary_key = (--lastdest)->primary_key();

    auto source_itrr = source.find(src_primary_key);
    source_itrr++;
    uint16_t batch_counter = 0;

    while (batch_counter < batch_size && source_itrr != source.end()) {
        destination.emplace(code, [&](auto &e){
            mapper(e, *source_itrr); // source_itrr is iterator, so pass it dereferenced
        });
        ++source_itrr;
        ++batch_counter;
    }
}
    migrate_table<regmembers>(get_self(), batch_size, get_self(), NEW_SCOPE, [](member& dest, member const& src){ // dereferenced `src` is const object
        dest.sender = src.sender;
        dest.agreedtermsversion = src.agreedtermsversion;
    });
1
  • That looks like the code I was looking for. I have since moved on with a verbose and repetitive approach but this would have been what I needed at the time. Thanks. Jul 8, 2019 at 22:33

Your Answer

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

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