CRTP Mixin中调用可变参数基类protected成员函数的优化方案咨询
CRTP Mixin中调用基类protected成员函数的优雅实现
背景与问题
我正在为派生类构建CRTP Mixin,核心需求是:
- 自动调用所有基类中存在的
fooImpl成员函数 - 这些基类的
fooImpl必须是protected的,不能暴露给外部用户
我最初写了如下代码:
#include <iostream> struct A { protected: void fooImpl() { std::cout << "A::fooImpl"; } }; struct C {}; template <typename... T> struct B : T... { void foo() { auto visitor = [](auto& s) { if constexpr (requires { s.fooImpl(); }) s.fooImpl(); }; (visitor(static_cast<T&>(*this)), ...); } }; int main() { B<A, C> b; b.foo(); return 0; }
这段代码的行为不符合预期:它确实没有调用C的fooImpl(符合预期),但也没有调用A的fooImpl。我推测这是因为static_cast<T&>(*this)导致fooImpl的protected可见性被限制?这种情况是否符合C++标准的预期?另外,之前关于基类protected构造器访问的讨论是否适用于这个场景?
现有解决方案(不够优雅)
我找到了两种可行但不够理想的实现方式:
方案1:CRTP友元转发
#include <iostream> template <typename S> struct A { friend S; private: void fooImpl() { std::cout << "A::fooImpl"; } }; template <typename S> struct C {}; template <template <typename> class... T> struct B : T<B<T...>>... { void foo() { auto visitor = [](auto& s) { if constexpr (requires { s.fooImpl(); }) s.fooImpl(); }; (visitor(static_cast<T<B<T...>>&>(*this)), ...); } };
这个方案能正常工作,但要求所有基类都改成模板类并将派生类设为友元,需要大量重构现有代码,对已有类的侵入性太强。
方案2:改为public成员并通过覆盖隐藏
#include <iostream> struct A { public: void foo() { std::cout << "A::foo"; } }; struct C {}; template <typename... T> struct B : T... { void foo() { auto visitor = [](auto& s) { if constexpr (requires { s.foo(); }) s.foo(); }; (visitor(static_cast<T&>(*this)), ...); } };
这个方案也可行,但把原本需要protected的成员改成了public,依赖派生类的foo来隐藏基类的同名函数,设计上不够严谨,有点过度设计的感觉。
求助
有没有更优雅的实现方式?比如利用C++20及以后的特性,实现更少样板代码、对现有基类侵入性更低的方案?
内容的提问来源于stack exchange,提问作者rath3t
相关产品推荐
相关产品推荐

