Это частный случай этот вопрос где этот ответ не работает напрямую
struct hurg {};
class furg {
public:
template <class F>
void for_each_hurg(F&& f) const {
for (auto& h : hurgs) {
f(h);
}
}
template <class F>
void for_each_hurg(F&& f) {
for (auto& h : hurgs) {
f(h);
}
}
private:
std::vector<hurg> hurgs;
};
Использование:
furg f;
const auto& cf = f;
f.for_each_hurg([](hurg& h) { });
cf.for_each_hurg([](const hurg& h) { });
Код для const
и неconst
версии идентичны, но только потому, что auto& h
делает вывод, const hurg&
в первом случае и hurg&
во втором случае.
В духе ранее связанных с Решение Скотта Мейерса, Я придумал следующее:
template <class F>
void for_each_hurg(F&& f) {
const_cast<const furg&>(*this).for_each_hurg([&f](const hurg& h) {
f(const_cast<hurg&>(h));
});
}
Тем не менее, кажется, что это может быть больше проблем, чем стоит, особенно если типы длинные и если я не могу использовать общие лямбда-выражения C ++ 14.
Вы можете использовать статический шаблон функции-члена для пересылки *this
к параметру универсальной функции:
template<typename Self, typename F>
static void for_each_hurg(Self& s, F&& f) {
for (auto& h : s.hurgs) {
f(h);
}
}
template<typename F>
void for_each_hurg(F&& f) { for_each_hurg(*this, forward<F>(f))); }
template<typename F>
void for_each_hurg(F&& f) const { for_each_hurg(*this, forward<F>(f))); }
С появлением ссылочных квалификаторов для функций-членов общее решение заключается в в совершенстве вперед *this
, Это не всегда важно, так как вы все равно не хотите, чтобы функции-члены вызывались для значений rvalue. Я добавлю это здесь, так как я думаю, что это является частью более общего решения.
К несчастью, *this
всегда является lvalue, поэтому вам нужно выполнить дополнительный ручной уход в оболочках функций-членов:
template<typename Self, typename F>
static void for_each_hurg(Self&& s, F&& f) {
/* ... */
}
template<typename F>
void for_each_hurg(F&& f) && { for_each_hurg(move(*this), forward<F>(f))); }
template<typename F>
void for_each_hurg(F&& f) & { for_each_hurg(*this, forward<F>(f))); }
Что, к сожалению, не симметрично 🙁
Также возможно реализовать вышеупомянутое через шаблон функции друга. Это может иметь два преимущества:
furg
Быть шаблоном класса уменьшает количество шаблонов функций, с которыми приходится иметь дело компилятору (по одному на шаблон класса, а не по одному на экземпляр). Однако обычно для этого требуется некоторый шаблонный код и предварительные декларации.furg f; for_each_hurg(furg, [](hurg){}); furg.for_each_hurg([](hurg){});
(Когда неквалифицированный поиск находит функцию-член, он не выполняет / игнорирует результаты ADL. Следовательно, вам нужно поместить функцию Friend в область пространства имен, чтобы иметь возможность обращаться к ней через квалифицированный идентификатор. из оберток нестатических функций-членов.)Кроме того, вы должны защитить этот шаблон функции от жадности; либо положить его в какой-то namespace detail
или добавление условия enable-if. Это, вероятно, не стоит усилий.