Почему std :: is_invocable , std :: decay_t <int>> :: значение равно false? - PullRequest
1 голос
/ 24 апреля 2020
std::is_invocable<std::decay_t<void(int&)>, std::decay_t<int>>::value

оценивается как ложное.

Но

void(int&) распадается до void*(int&)

и int до int

и я могу использовать std::invoke вот так:

void f(int&);
...
auto* fp = f;
int i = 0;
std::invoke(fp, i);

Я наткнулся на это, когда смотрел на конструктор std::thread:

 template<typename _Callable, typename... _Args,
             typename = _Require<__not_same<_Callable>>>
      explicit
      thread(_Callable&& __f, _Args&&... __args)
      {
        static_assert( __is_invocable<typename decay<_Callable>::type,
                                      typename decay<_Args>::type...>::value,
          "std::thread arguments must be invocable after conversion to rvalues"
          );

Я понимаю, почему передача ссылок на * Конструктор 1022 * обескуражен (мы все еще можем использовать std::ref()), но я не могу понять, почему void *(int&) нельзя вызывать с int.

1 Ответ

4 голосов
/ 24 апреля 2020

std::is_invocable<..., int> пытается использовать int rvalue в качестве аргумента. Это эквивалентно std::is_invocable<..., int &&>.

Использование std::is_invocable<..., int &>.


std::is_invocable

... Формально, определяет, является ли INVOKE(declval<Fn>(), declval<ArgTypes>()...) правильно сформированным ...

Даже если мы игнорируем, что такое INVOKE, вы можете видеть, что is_invocable определяется с помощью std::declval<ArgType>(), который возвращает ArgType &&.

ArgType &&, ну, в общем, ссылка на значение. Если ArgType не является ссылкой lvalue, в этом случае ArgType && эквивалентно ArgType и является ссылкой lvalue (согласно правилам свертывания ссылок).

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