C++使用std::conditional选择继承基类报非直接基类错误
错误根因
你在类继承列表中直接继承了std::conditional<...>模板实例本身,而非它筛选出的目标类型。std::conditional本质是一个编译期选择工具类,真正符合你条件的目标类型是它的内嵌成员type,你之前的写法相当于让Last继承了conditional工具类,而非Derived1/Derived2,但在构造函数里你却调用了std::conditional<...>::type也就是Derived1/Derived2的构造函数,编译器检测到你构造的类型不是Last的基类,就会抛出对应报错。
模板未实例化时只会做基础语法校验,不会检查继承关系、基类构造合法性这类实例化相关逻辑,所以你在创建Last对象前不会触发编译错误。这个问题和菱形继承、虚继承没有任何关联,不要被相似的报错信息误导。
修复方案
最简洁的写法是提前给选中的基类定义别名,避免重复书写冗长的conditional判断,同时修正继承的目标类型:
#include <iostream> #include <type_traits> template< class > class Base; template< class T, class ...Args > class Base < T(Args...) > { public: Base(int a) { std::cout << "Base constructor " << a << std::endl; } }; template< class > class Derived1; template< class ...Args > class Derived1 < void(Args...) > : public Base< void(Args...) > { public: Derived1(int a) : Base< void(Args...) >(a) { std::cout << "Derived1 constructor " << a << std::endl; } }; template< class > class Derived2; template< class T, class ...Args > class Derived2 < T(Args...) > : public Base< T(Args...) > { public: Derived2(int a) : Base< T(Args...) >(a) { std::cout << "Derived2 constructor " << a << std::endl; } }; // 提前定义编译期选中的基类别名 template<class T, class... Args> using LastBaseT = typename std::conditional< std::is_void<T>::value, Derived1<void(Args...)>, Derived2<T(Args...)> >::type; template< class > class Last; template< class T, class ...Args > class Last< T(Args...) > : public LastBaseT<T, Args...> { public: Last(int a) : LastBaseT<T, Args...>(a) { std::cout << "Last constructor " << a << std::endl; } }; int main() { Last<int(int)> last(1); return 0; }
修复后实例化Last<int(int)>会按预期依次调用Base、Derived2、Last的构造函数,输出对应日志。
优化提示
- 如果你使用C++14及以上标准,可以直接用标准库提供的
std::conditional_t别名模板,省略手写typename ...::type的步骤,写法更简洁:template<class T, class... Args> using LastBaseT = std::conditional_t< std::is_void<T>::value, Derived1<void(Args...)>, Derived2<T(Args...)> >; - 所有编译期选择基类的场景都建议提前抽出基类别名,既可以减少重复代码,也能避免继承列表、初始化列表两处条件判断写不一致的笔误。
- 直接在继承列表手写
typename std::conditional<...>::type也能通过编译,但重复书写相同逻辑的维护成本更高,不推荐使用。
内容的提问来源于stack exchange,提问作者pl0xxxy
相关产品推荐
相关产品推荐

