Это потому, что псевдоним типа члена, такой как std::decay<T>::type
, не подлежит вычету.
template<typename T>
void call_me(std::decay_t<T>) {}
// won't work :(
// call_me(1);
Я не думаю, что ваш класс должен разрушать тип.Вместо этого ваш класс должен заявить, что ему требуется тип объекта, и переместить затухание в функцию make:
template <typename F> // requires std::is_object_v<F>
class WillInvoke
{
static_assert(std::is_object_v<F>,
"WillInvoke requires F to be an object type"
);
public:
WillInvoke(F f) : f(std::move(f)) { }
void CallNow() { f(); }
private:
F f;
};
template <typename F>
auto make_WillInvoke(F && f) -> WillInvoke<std::decay_t<F>>
{
return WillInvoke<std::decay_t<F>>(std::forward<F>(f));
}
Приятно то, что в C ++ 20 вы можете раскомментировать require и позволить компиляторуприменить это на сайте вызова.