Проблема порядка параметров параметров шаблона - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть шаблонная оболочка функции, которую я пытаюсь обновить до синтаксиса C ++ 11 (переменные параметры).

Моя проблема в том, что я попал в "catch 22", где 'Args...'должен быть последним параметром шаблона, но в то же время не может быть определен после параметра шаблона указателя функции.

Есть идеи, если это действительно можно решить?

  template <typename... Args, void(*Function)(Args...)>
  class function
  {
  public:

    void operator ()(Args... args) const
    {
      (*Function)(std::forward<Args...>(args...));
    }
  };

1 Ответ

0 голосов
/ 21 февраля 2019

Возможный способ - использовать специализацию шаблона

template <typename>
struct myFunc;

template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
 {
   // ...
 };

, но таким образом вы перехватываете (в качестве параметра шаблона) тип указателя функции, а не указателя функциисам;поэтому вам нужно каким-то образом передать указатель на функцию (конструктор?).

Также обратите внимание, что если вы хотите использовать идеальную пересылку, вы должны преобразовать operator() в методе шаблона, получающем аргументы как универсальные ссылки(&&).

Что-то следующее

   template <typename ... As>
   R operator() (As && ... args) const
    {
      return fun(std::forward<As>(args)...);
    }

, где fun - указатель типа R(*)(Args...).

Ниже приведен полный пример компиляции

#include <iostream>
#include <utility>

int foo (int, long)
 { return 42; }

template <typename>
struct myFunc;

template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
 {
   using  funPnt = R(*)(Args...);

   funPnt  fun = nullptr;

   myFunc (funPnt f0) : fun{f0}
    { }

   template <typename ... As>
   R operator() (As && ... args) const
    {
      return fun(std::forward<As>(args)...);
    }
 };

int main ()
 { 
   myFunc<decltype(&foo)>  mf0{&foo};

   std::cout << mf0(1, 2l) << std::endl;
 }

Если вам действительно нужна функция указателя в качестве параметра шаблона (но, таким образом, каждая функция определяет свой тип; это может быть хорошим или плохим в соответствии с вашими потребностями), вы можете написатьmyFunc структура получает перед типом (тот же тип указателя) и затем значение этого типа.

Итак

template <typename T, T>
struct myFunc;

template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<R(*)(Args...), Func>
 {
   template <typename ... As>
   R operator() (As && ... args) const
    {
      return Func(std::forward<As>(args)...);
    }
 };

, который может быть объявлен

 myFunc<decltype(&foo), foo>  mf0;

Если вы можете использовать C ++ 17, вы можете упростить использование auto для типа значений шаблона;так что вы можете избежать типа

template <auto>
struct myFunc;

template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<Func>
 {
   template <typename ... As>
   R operator() (As && ... args) const
    {
      return Func(std::forward<As>(args)...);
    }
 };

и создать объект myFunc следующим образом

myFunc<&foo> mf0;

Добавление: если вы можете использовать C ++ 17, вы можете определитьруководство по выводу для первого примера (указатель как член, а не как параметр значения шаблона)

template <typename R, typename ... Args>
myFunc (R(*)(Args...))  -> myFunc<R(*)(Args...)>;

, поэтому вместо

myFunc<decltype(&foo)>  mf0{&foo};

вы можете просто написать

myFunc  mf0{&foo};

Не по теме: надеюсь, вы знаете, что изобретаете велосипед.Как предполагает NathanOliver, стандарт обеспечивает std::function.

...