Задать вопрос
Dyikot
@Dyikot

Почему без std::remove_reference_t не работает?

Реализую
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>>);
  • Вопрос задан
  • 194 просмотра
Подписаться 2 Простой 2 комментария
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Вообще, не вижу противоречия. У вас же там tfunc&&, его вы пытаетесь к void* привести и к нему применяете remove reference.

Попробуйте в ваш static assert добавить std::move и он обвалится.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы