Реализую
non-ownable callable wrapper
template<typename T>
class CallableView;
template<typename TReturn, typename... TArgs>
class CallableView<TReturn(TArgs...)>
{
public:
template<CFunc<TReturn, TArgs...> TFunc>
CallableView(TFunc&& callable):
_callable(&callable),
_erased(OnErasedCall<std::remove_reference_t<TFunc>>)
{}
CallableView(const CallableView& view):
_callable(view._callable),
_erased(view._erased)
{}
CallableView(CallableView&& view) = delete;
TReturn operator()(TArgs... args) const
{
return _erased(_callable, std::forward<TArgs>(args)...);
}
private:
template<typename T>
static TReturn OnErasedCall(void* callable, TArgs... args)
{
return (*static_cast<T*>(callable))(std::forward<TArgs>(args)...);
}
private:
void* _callable;
TReturn(*_erased)(void*, TArgs...);
};
template<typename TCallable>
CallableView(TCallable&&) -> CallableView<std::invoke_result_t<TCallable>()>;
и почему-то если передавать ссылку на lvalue без std::remove_reference_t в конструкторе то будут ошибки:
1) term does not evaluate to a function taking 0 arguments
2) 'abstract declarator': you cannot create a pointer to a reference
в примере:
auto f = [] {};
CallableView view = f;
view();
Но если с ним, то все работает. Почему же так? Ведь при такой проверки типы одинаковые:
auto f = [] {};
using F = decltype(f);
static_assert(std::same_as<F, std::remove_reference_t<F>>);