шаблон Расширение пакета параметров при вызове функции с массивом данных - PullRequest
0 голосов
/ 12 июня 2018

Попытка избежать перегрузки моей функции из-за количества параметров x.

//T.. Types,C Class,R Return type
template<typename R = void,class C,typename T1,typename T2>
R callClassFunction(C& classname,void (C::*func)(T1,T2), void** myd)
{
    return (classname.*func)(*((T1*)myd[0]), *((T2*)myd[1]));
}

Можно ли сделать это с помощью шаблона с переменным числом аргументов?

Я не могу определить правильный синтаксис из-зав массив данных.

Ответы [ 2 ]

0 голосов
/ 12 июня 2018

Это должно работать:

template <typename R, class C, typename... Ts, size_t... Is>
R impl(C& instance, R (C::*func)(Ts...), void** data, index_sequence<Is...>)
{
    return (instance.*pmf)(*static_cast<Ts*>(data[Is])...);
}

template <typename R, class C, typename... Ts>
R callClassFunction(C& instance, R (C::*func)(Ts...), void** data)
{
    return impl(instance, func, data, make_index_sequence<sizeof...(Ts)>{});
}

index_sequence - это C ++ 14, но может быть реализовано в C ++ 11, вы можете найти много реализаций в SO.

Ключто есть, мы строим эту последовательность целых чисел, и мы можем использовать их для индексации в void*.Эта последовательность имеет тот же размер, что и Ts, поэтому мы можем распаковать Ts и Is вместе.

Обратите внимание, что это будет работать только для не-1013 * указателей на функции-члены.Вам нужно будет сделать это снова для указателей на const функции-члены.

Кроме того, если функция-член получает ссылку, это не совсем работает - вам потребуются некоторые другие манипуляции.Я оставлю это в качестве упражнения для читателя.

0 голосов
/ 12 июня 2018

Можно ли сделать это с помощью шаблона с переменными числами?

Если я правильно понимаю, что вы хотите, вы ищете что-то следующее

template<typename R, class C, typename ... Ts1, typename ... Ts2>
R callClassFunction (C & classname, R (C::*func)(Ts1...), Ts2 && ... as)
 { return (classname.*func)(std::forward<Ts2>(as)...); }

Я имею в виду:

1) тип возвращаемого значения R может быть выведен из указателя метода, и нет необходимости устанавливать его по умолчанию на void

2) список переменныхаргументов (Ts1...) также можно вывести из указателя метода

3) для следующего параметра, переданного в callClassFunction(), для передачи в func(), я предлагаю другой список переменныхтипы Ts2..., потому что нет необходимости, чтобы Ts1... равнялся Ts2...;нужно только, чтобы типы Ts2... были преобразованы в типы Ts1...;таким образом, вы можете передать "123" (char const * или char[]), а не обязательно std::string("123"), методу, ожидающему std::string

.пример

#include <string>
#include <type_traits>

struct foo
 {
   long bar (std::string const & a, int b, char c)
    { return a.size() + b + c; }

   void baz (std::string const &, int, char)
    { }
 };

template<typename R, class C, typename ... Ts1, typename ... Ts2>
R callClassFunction (C & classname, R (C::*func)(Ts1...), Ts2 && ... as)
 { return (classname.*func)(std::forward<Ts2>(as)...); }

int main ()
 { 
   foo f;

   auto r { callClassFunction(f, &foo::bar, "123", 4, '5') };

   static_assert( std::is_same<long, decltype(r)>{}, "!" );

   callClassFunction(f, &foo::baz, "123", 4, '5');
 }

- РЕДАКТИРОВАТЬ -

Операционный запрос

Что если я хочу сохранить массив void*и использую типы Ts1 для приведения из void*

Я нахожу это чрезвычайно опасным, но ... если вы определите шаблон, используя следующее

template <typename T0, typename...>
using only_first = T0;

Вы можете использовать его для наложения в callClassFunction() списка void * параметров длиной до Ts1... (переименован в Ts..., потому что больше нет Ts2...)

template<typename R, class C, typename ... Ts>
R callClassFunction (C & classname, R (C::*func)(Ts...),
                     only_first<void *, Ts> ... as)

и, вВ теле функции вы можете использовать Ts..., чтобы привести void * указатели к Ts... указателям

return (classname.*func)(*static_cast<Ts*>(as)...);

Я повторяю: я нахожу это чрезвычайно опасным, и мне страшно думать об этом решении.

Но если вы действительно хотите ... ниже приведен модифицированный полный рабочий пример

#include <string>
#include <type_traits>

struct foo
 {
   long bar (int a, double b, char c)
    { return a + b + c; }

   void baz (int, double, char)
    { }
 };

template <typename T0, typename...>
using only_first = T0;

template<typename R, class C, typename ... Ts>
R callClassFunction (C & classname, R (C::*func)(Ts...),
                     only_first<void *, Ts> ... as)
 { return (classname.*func)(*static_cast<Ts*>(as)...); }

int main ()
 { 
   foo f;

   int     i { 1 };
   double  d { 2.0 };
   char    c { '3' };

   auto r { callClassFunction(f, &foo::bar, (void*)&i, (void*)&d, (void*)&c) };

   static_assert( std::is_same<long, decltype(r)>{}, "!" );

   callClassFunction(f, &foo::baz, (void*)&i, (void*)&d, (void*)&c);
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...