эмм... variadic-pack в нешаблонную функцию
От: niXman Ниоткуда https://github.com/niXman
Дата: 12.10.16 14:41
Оценка:
привет!

снова хочу странного =)

struct somestruct {
    template<typename... Args>
    shared_buffer pack(const Args&... args) {
        return pack2(args...);
    }

private:
    shared_buffer pack2(???);
}; // somestruct


т.е. хочется каким-то образом(возможно даже используя tuple<>), передать args в send2(), которая реализована в cpp`шке.

для фундаментальных типов все просто — преобразуем args в массив указателей на void, и добавляем какие-то ID`ы, идентифицирующие типы.
но со всеми остальными(в том числе и юзерскими типами) типами все как-то не перспективно...

кто-то задавался похожим вопросом?

спасибо.


UP.
ну, наверное, можно что-то зарукоблудить используя std::type_index и карту(которую нужно инициализировать вручную) соответствующих обработчиков...
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 12.10.2016 14:48 niXman . Предыдущая версия . Еще …
Отредактировано 12.10.2016 14:42 niXman . Предыдущая версия .
Re: эмм... variadic-pack в нешаблонную функцию
От: PM  
Дата: 13.10.16 05:17
Оценка: +1
Здравствуйте, niXman, Вы писали:

[...]


X>для фундаментальных типов все просто — преобразуем args в массив указателей на void, и добавляем какие-то ID`ы, идентифицирующие типы.

X>но со всеми остальными(в том числе и юзерскими типами) типами все как-то не перспективно...

tuple здесь не поможет, т.к. для разных Args будут разные типы tuple. RTTI в виде std::type_index тоже как-то не очень. Идея с массивом void* правильная, но вместо идентифкаторв типов можно передавать массив функций-обработчиков для значения каждого типа:

#include <iostream>

struct shared_buffer {};

// то что тебе нужно делать для каждого типа
shared_buffer do_pack(int arg);
shared_buffer do_pack(double arg);

struct foo {
    // пользовательскиме типы тоже не проблема
    friend shared_buffer do_pack(foo const& arg);
};


struct somestruct {
    template<typename... Args>
    shared_buffer pack(const Args&... args) {
        // заворачиваем do_pack для каждого типа в массив функций
        arg_pack_fn fns[] = { &wrap_do_pack<Args>... };
        // преобразуем аргументы в массив void const*
        void const* data[] = { std::addressof(args)... };

        return pack2(fns, data, sizeof...(Args));
    }

private:
    using arg_pack_fn = shared_buffer (*)(void const* arg);

    // обертка для функций do_pack(T) чтобы привести к arg_pack_fn
    template<typename T>
    static shared_buffer wrap_do_pack(void const* arg) {
        return do_pack(*static_cast<T const*>(arg));
    }
    
    shared_buffer pack2(arg_pack_fn pack_fns[], void const* args[], size_t count);
};

// implementation in .cpp

shared_buffer do_pack(int arg) {
    std::cout << arg << ' ';
}

shared_buffer do_pack(double arg) {
    std::cout << arg << ' ';
}

shared_buffer do_pack(foo const& arg) {
    std::cout << "foo ";
}

shared_buffer somestruct::pack2(arg_pack_fn pack_fns[], void const* args[], size_t count) {
    for (size_t i = 0; i != count; ++i) {
        pack_fns[i](args[i]);
    }
}

int main() {
  somestruct ss;
  ss.pack(foo{}, 1, 3.14); // should print "foo 1 3.14 "
}


http://ideone.com/Ol1KUx
Re[2]: эмм... variadic-pack в нешаблонную функцию
От: niXman Ниоткуда https://github.com/niXman
Дата: 13.10.16 08:22
Оценка:
Здравствуйте, PM,

ну да, с массивом функций — хорошая идея.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re: эмм... variadic-pack в нешаблонную функцию
От: Evgeny.Panasyuk Россия  
Дата: 13.10.16 11:01
Оценка:
Здравствуйте, niXman, Вы писали:

X>т.е. хочется каким-то образом(возможно даже используя tuple<>), передать args в send2(), которая реализована в cpp`шке.


Подробнее, непонятно что требуется. Что за send2?

P.S. Судя по всему тебе нужно стереть типы — возможно подойдёт Boost.TypeErasure, а может и просто std::function.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.