Мне нравится @ ответ RealFresh .Это демонстрирует, как именно «инкапсулирует» защищенную доступность на самом деле.Но приведение ссылки на объектный объект базового класса к ссылке на объектный объект производного класса и последующая обработка этого как одного может быстро привести к неопределенному поведению.
Однако идея извлечения члена c
вполне обоснована.Мы можем сделать это без риска UB с помощью простой утилиты:
template<class S>
constexpr decltype(auto) stack_c(S&& s) {
using base = std::decay_t<S>;
struct extractor : base {
using base::c;
};
constexpr auto c_ptr = &extractor::c;
return std::forward<S>(s).*c_ptr;
}
Благодаря тому, как работает выражение &extractor::c
, мы фактически получаем указатель на член base
(специализация std::stack
) с именем c
.Цель extractor
- сделать имя общедоступным через объявление использования.
Затем мы пересылаем ссылку на него, сохраняем категорию значений и все.Это капля замены в @ RealFresh's предложении использовать std::equal
:
bool areEqual = std::equal(
stack_c(s1).begin(), stack_c(s1).end(),
stack_c(s2).begin(), stack_c(s2).end(),
[](auto const& p1, auto const& p2) {
return first && second && (p1 == p2 || *p1 == *p2);
}
);
Смотрите его вживую