可变参数模板继承场景下基类成员名称隐藏的合规解决方案问询
解决方法
你原有代码中的using Composite<Args...>::foo属于错误写法:该语句试图引入当前派生类自身的foo成员,而C++标准要求using声明引入继承的成员时必须指定基类类型,因此GCC会严格抛出"不是基类"的编译错误。VS2017能正常编译是MSVC的非标准扩展宽松处理导致的,不属于标准兼容的写法。
你要解决基类foo被派生类同名方法隐藏的问题,只需要把所有基类的foo成员都引入到派生类作用域即可,C++17及以上标准支持可变参数包展开的using声明,直接替换原有错误的using行即可:
template <typename ... Args> struct Composite: Args... { // 标准写法:展开所有基类的foo成员引入当前作用域 using Args::foo...; void foo(float exposure) { return this->foo(*this, exposure); } void internalBar(float e) { std::cout << "it works" << e; } };
兼容性说明
如果需要兼容C++17之前的旧标准,可以通过构造继承链的方式间接实现,示例如下:
// 递归继承链的辅助模板 template <typename... Args> struct CompositeBase; template <> struct CompositeBase<> {}; template <typename First, typename... Rest> struct CompositeBase<First, Rest...> : First, CompositeBase<Rest...> { using First::foo; using CompositeBase<Rest...>::foo; }; template <typename... Args> struct Composite : CompositeBase<Args...> { using CompositeBase<Args...>::foo; void foo(float exposure) { return this->foo(*this, exposure); } void internalBar(float e) { std::cout << "it works" << e; } };
目前主流编译器(GCC 7+、Clang 5+、VS2017+)都默认支持C++17,直接使用可变参数using的写法即可满足跨编译器兼容需求。
内容的提问来源于stack exchange,提问作者edenroz
相关产品推荐
相关产品推荐

