C ++ 11 метод, чтобы проверить, являются ли аргументы шаблона «доступными» - PullRequest
3 голосов
/ 01 июля 2019

C ++ 17 представил std :: invocable , но мне интересно решение C ++ 11-only. Моя первая мысль - использовать std :: result_of .

Мой текущий код выглядит следующим образом (SchedulingPolicy является enum class):

template<typename Function, typename... Args,
    typename = typename std::result_of<Function&&(Args&&...)>::type>
int start(size_t stackSize, size_t queuedSignals, size_t signalActions,
    uint8_t priority, SchedulingPolicy schedulingPolicy, Function&& function,
    Args&&... args)
{
  // main implementation
}

template<typename Function, typename... Args,
    typename = typename std::result_of<Function&&(Args&&...)>::type>
int start(size_t stackSize, size_t queuedSignals, size_t signalActions,
    uint8_t priority, Function&& function, Args&&... args)
{
  return start(stackSize, queuedSignals, signalActions, priority,
      SchedulingPolicy::roundRobin, std::forward<Function>(function),
      std::forward<Args>(args)...);
}

template<typename Function, typename... Args,
    typename = typename std::result_of<Function&&(Args&&...)>::type>
int start(size_t stackSize, uint8_t priority, Function&& function,
Args&&... args)
{
  return start(stackSize, 0, 0, priority, SchedulingPolicy::roundRobin,
      std::forward<Function>(function), std::forward<Args>(args)...);
}

template<typename Function, typename... Args,
    typename = typename std::result_of<Function&&(Args&&...)>::type>
int start(size_t stackSize, uint8_t priority,
    SchedulingPolicy schedulingPolicy, Function&& function, Args&&... args)
{
  return start(stackSize, 0, 0, priority, schedulingPolicy,
      std::forward<Function>(function), std::forward<Args>(args)...);
}

Существует в основном одна основная реализация - со всеми возможными аргументами - и 3 обертки - у которых не все аргументы. Я использую SFINAE в аргументах шаблона - typename = typename std::result_of<Function&&(Args&&...)>::type - иначе одна из оболочек вызывает бесконечную рекурсию. Кажется, это работает нормально, но я провел только очень ограниченное тестирование. Однако на cppreference я прочитал мотивацию обесценивания std::result_of в пользу std::invoke_result (кстати, есть информация, почему я использую ссылки на r-значения вместо std::result_of<Function(Args...)>), что заставило меня задуматься, используется ли я правильно или может быть (в реальной жизни) ситуации, когда это на самом деле потерпит неудачу, даже если переданные аргументы верны? Мой сценарий использования передает все возможные «вызываемые объекты»: обычные функции, функции-члены, лямбды или функторы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...