Введение
Предположим, что мы имеем линейную иерархию типов, как показано ниже:
Тогда то, что я хочу, - это механизм возврата наименьшего общего предка из произвольного числа типов в этой линии.
Попытка кода
template<typename...Ts>
struct LCA;
template<typename T1, typename T2, typename...Ts>
struct LCA<T1, T2, Ts...>
{
using base = typename std::conditional
<
std::is_base_of<T1, T2>::value, T1,
typename std::conditional <
std::is_base_of<T2, T1>::value, T2, void
>::type
>::type;
using type = typename LCA<base, Ts...>::type;
};
template<typename T>
struct LCA<T>
{
using type = T;
};
Использовать регистр
Мой пример использования довольно типичен: при создании некоторых инструментов iterator
я хочу извлечь "самый ограничительный" тип итератора, поэтому, поскольку существует (тип) линейной иерархии в итераторах, я должен иметь возможность восхождения к иерархии как сколько нужно:
LCA<Bidirectional, RandomAccess, RandomAccess> -> Bidirectional
LCA<RandomAccess, Input, Forward> -> Input
Вопросы
-
Есть ли более сжатый/идиоматический способ обработки случая ошибки, где два или более типа являются незнакомыми для иерархии? Текущий подход заключается в возврате
void
, который, надеюсь, даст отказ в большинстве контекстов, где тип фактически используется. -
Является ли использование дополнительного члена
base
в первой проблеме специализации? Должен ли я извлечь эту функциональность в отдельный класс и использовать ее в строкеtype
до поддерживать единообразие? -
Есть ли алгоритм, который уменьшил количество экземпляров? Есть ли лучший способ, чем попарные сравнения, так что сложность алгоритма может быть уменьшена?
-
Может ли кто-нибудь масштабировать до нелинейных иерархий и запрашивать по глубине дерево иерархии? Что будет хорошим "разрывом связи" в этом случае (для типов на одном уровне)?