Я пытаюсь реализовать свой собственный std::is_base_of
для моего программирования AVR (avr-g cc пока не поддерживает <type_traits>
. Я вдохновился возможной реализацией на cppreference page , она работала для одиночной проверки типа. Однако я хочу добиться статически выполняемых проверок достоверности множественных типов наследования одного базового класса.
Для простоты я использую std::is_base_of
для фактической проверки ниже , однако мое реальное решение близко к тому, что на странице cppreference, связанной выше.
Я буду использовать его для отправки тегов, более конкретно, чтобы разрешить теги параметров в любом порядке.
Теги параметров
struct tOption {};
struct tThis : public tOption {};
struct tThat : public tOption {};
struct tElse {}; // Wrongly defined option tag!
Структура одного объекта проверки наследия
template<typename TBase, typename TCandidate>
struct isBaseOf {
isBaseOf() = delete;
static const bool value = std::is_base_of<TBase, TCandidate>::value;
};
static_assert(isBaseOf<tOption, tThat>::value, "Invalid option tag!"); // OK!
static_assert(isBaseOf<tOption, tElse>::value, "Invalid option tag!"); // ERROR! Invalid option tag!
Попытка многократных проверок (в дополнение к декларации isBaseOf
выше)
template<typename TBase, typename TCandidate, typename... TRest>
struct isBaseOf {
isBaseOf() = delete;
static const bool value = isBaseOf<TBase, TRest...>::value &&
std::is_base_of<TBase, TCandidate>::value;
};
Это не работает. Из того, что я вижу, я не могу переопределить шаблон с помощью ди Различное количество типов. Тем не менее, мне нужно по крайней мере два типа в последней конструкции шаблона. Я попытался использовать TBase в качестве единственного параметра и просто установил значение true, но та же проблема все еще здесь: ошибка: объявлена заново с 3 параметрами шаблона
Использование
Как уже упоминалось, это ограничивается одной проверкой. Поскольку мой класс (здесь не показан) использует шаблоны variadi c для любого количества тегов параметров (а avr-g cc не поддерживает полноценный c ++ 14 с циклами for в функциях constexpr
), я хочу быть в состоянии использовать распаковку параметров и все еще проверять, что все теги параметров имеют наследие моего базового тега (tOption
).
template<typename... TOptions>
class tMyClass {
static_assert(isBaseOf<tOption, TOptions...>::value, "Invalid option tag(s)!"); // <--- THIS
// ...
};
Использование функций - Уродливые и нежелательные
Я заставил его работать, используя функцию вместо другой структуры, но я думаю, что это сбивает с толку. Я предпочел бы иметь один способ решения проблемы во всем рекурсивном (stati c) стеке. Кроме того, это заставляет меня создавать каждый тег, который не очень аккуратный IMO.
template<typename TBase, typename TCandidate>
constexpr bool isBaseOf2(const TBase&, const TCandidate&) {
return std::is_base_of<TBase, TCandidate>::value;
}
template<typename TBase, typename TCandidate, typename... TRest>
constexpr bool isBaseOf2(const TBase& base, const TCandidate&, const TRest&... rest) {
return isBaseOf2(base, rest...) && std::is_base_of<TBase, TCandidate>::value;
}
static_assert(isBaseOf2(tOption{}, tThis{}, tThat{}), "Invalid option tag(s)!"); // OK!
static_assert(isBaseOf2(tOption{}, tThis{}, tElse{}), "Invalid option tag(s)!"); // ERROR! Invalid option tag(s)!
Есть ли способ переопределить шаблон структуры с другим числом параметров , например, в Попытка нескольких проверок выше?