В настоящее время я работаю над проектом в стиле Arduino «gameboy», где пытаюсь создать библиотеку, которая будет работать как игровой движок. В Arduino IDE нет C++ STL при использовании платы AVR, поэтому я пытаюсь реализовать кучу вещей из стандартной библиотеки шаблонов, таких как контейнеры и признаки типов. В настоящее время я пытаюсь реализовать std::regular_invocable как метафункцию, поскольку в Arduino IDE нет никаких концепций (судя по всему, она компилируется в C++14). Поскольку std::regular_invocable полагается на выражение require, неявно гарантируя, что все сохраняет равенство, у меня возникли проблемы с реализацией этого в IDE Arduino. У меня реализованы std::is_invocable и std::invoke.
вот моя реализация std::invocable:
namespace __detail {
struct __do_invocable_concept_impl {
template<class _Fn, class... _Args,
class = decltype(invoke(forward<_Fn>(declval<_Fn&&>()), forward<_Args>(declval<_Args&&>())...))>
static true_type __test(int);
template<class, class>
static false_type __test(...);
};
template<class _Fn, class... _Args>
struct __invocable_concept_impl : public __do_invocable_concept_impl {
using type = decltype(__test<_Fn, _Args...>(0));
};
}
template<class _Fn, class... _Args>
struct invocable
: public __detail::__invocable_concept_impl<_Fn, _Args...>::type { };
Реализация std::invocable и std::regular_invocable в libstdc++:
template<class _Fn, class... _Args>
concept invocable =
requires(_Fn&& __f, _Args&&... __args) {
invoke(forward<_Fn>(__f), forward<_Args>(__args)...);
};
template<class _Fn, class... _Args>
concept regular_invocable = invocable<_Fn, _Args...>;
// this automatically checks for equality preservation
Я не знаком с тем, как работает выражение require, поскольку я мало что писал в новых версиях C++, но похоже, что вы создаете неинициализированные переменные в параметрах, которые вы можете передать в функцию и выполнить сравнение.
Есть ли способ проверить, сохраняет ли вызываемый тип и его аргументы равенство после вызова в С++ 14, не полагаясь на выражение require, гарантирующее, что все сохраняет равенство?
Извините, если это неправильно сформулировано или кажется глупым. Я самоучка, и это первый вопрос по программированию, который я где-либо публиковал.
Я пытался использовать declval для проверки равенства с помощью bool_constant, но не могу понять нашел способ сравнить тип _Fn&& с _Fn&&, который был передан в функцию вызова поскольку declval не должен быть оценен. Мне нужно иметь возможность проверить во время компиляции, если переменная типа _Fn и переменные в _Args... остаются равными после вызова.
@JeJo, например, если у вас есть requires(_Fn&& f)
в теле выражения, вы должны сделать что-то вроде auto prev = f
then 'invoke(forward<_Fn>(f));`, а затем проверить f == prev
, чтобы увидеть, изменилось ли f
. если f == prev
истинно, то оно сохраняет равенство.
Единственное решение — сделать regular_invocable
псевдонимом invocable
, как это делает стандартная библиотека. Нет, он не проверяет сохранение равенства неявно, компилятор не может этого сделать. Смотрите здесь.