C++ 基于模板模板参数实现混入式多继承遇模板参数不匹配编译错误
编译报错修复
报错根因
你碰到的type/value mismatch at argument 1 in template parameter list for 'template<class> class ... Methods' 错误,本质是模板模板参数的声明语法在旧C++标准下的兼容性问题:
在C++17将typename与class在模板模板参数场景的等价性纳入标准之前,声明模板模板参数时必须使用class占位符。如果写template <typename> typename... Methods,编译器会误将传入的Foo、Bar识别为普通类型,而非带单模板参数的类模板,最终触发类型/值不匹配的编译错误。
修复后的可运行代码
只需要调整Impl的模板参数声明,把模板模板参数包里的typename替换为class即可,其余逻辑完全保留原有设计:
#include <cstdio> template <typename T> struct Foo { Foo(T &t) : t_(t) { } void foo() { t_.call("foo"); } T &t_; }; template <typename T> struct Bar { Bar(T &t) : t_(t) { } void bar() { t_.call("bar"); } T &t_; }; // 调整点:模板模板参数使用class声明,兼容C++11及以上全标准 template <template <typename> class... Methods> struct Impl : public Methods<Impl>... { Impl() : Methods<Impl>(*this)... { } void call(const char *m) { printf(m); } }; int main() { auto t = Impl<Foo, Bar>(); t.foo(); t.bar(); }
补充说明
这套实现是标准的CRTP混入(mixin)模式:
- 每个能力类(
Foo、Bar)都持有顶层组合对象Impl的引用,不需要继承自公共基类,完全通过模板参数组合获得多类能力 - 构造时传递
*this的逻辑是合法的:虽然Impl在自身构造函数初始化列表阶段是不完整类型,但引用绑定不需要完整类型的大小信息,只要后续能力类不提前访问Impl的成员布局,就不会触发编译问题 - 这种实现没有运行时的虚函数开销,所有方法调用都是静态绑定,性能和手写多继承完全一致
内容的提问来源于stack exchange,提问作者Vladyslav Mozhvylo
相关产品推荐
相关产品推荐

