Как вывести параметры `std :: function` из реальной функции? - PullRequest
3 голосов
/ 07 мая 2019

Учитывая класс

class Foo {
 public:
  std::shared_ptr<const Bar> quux(const std::string&, std::uint32_t);
}

Я могу объявить std::function с тем же интерфейсом:

std::function<std::shared_ptr<const Bar>(const std::string&, std::uint32_t)> baz = ...

Существует ли способ сжатия этого объявления таким образом, чтобы аргументы шаблона к std::function были получены из объявления этого метода, что-то вроде:

std::function<functype(X::quux)> baz = ...

где functype - мнимый оператор C ++, аналогичный decltype. Есть ли способ сделать это / есть ли у такая возможность?

Я вижу, что метод на самом деле имеет немного другую подпись, так как он также принимает ссылку / указатель на объект this; для меня было бы хорошо получить такую ​​подпись.

1 Ответ

5 голосов
/ 07 мая 2019

Да, вы можете. Адаптация Как мне получить типы аргументов указателя на функцию в классе шаблонов с переменными параметрами? к вашему запросу, мы получим:

template<typename T> 
struct function_traits;  

template<typename R, typename C, typename ...Args> 
struct function_traits<R(C::*)(Args...)>
{
    using type = std::function<R(Args...)>;
};

class Bar;

class Foo {
 public:
  std::shared_ptr<const Bar> quux(const std::string&, std::uint32_t);
};

int main()
{
   std::cout << std::is_same<
     std::function<std::shared_ptr<const Bar>(const std::string&, std::uint32_t)>,
     function_traits<decltype(&Foo::quux)>::type>::value << std::endl;
}

Чтобы он работал с постоянными методами, вам понадобится другая специализация:

template<typename R, typename C, typename ...Args> 
struct function_traits<R(C::*)(Args...) const>
{
    using type = std::function<R(Args...)>;
};

Но у вас будут проблемы с перегруженными методами, потому что для устранения перегрузки вам все равно нужно будет указать аргументы.

...