You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于基类类型有条件地隐藏模板中的方法

问题

我定义了一个继承自std::vector或std::list的模板类Test,需要隐藏所有可修改底层容器大小的方法。我知道可以通过using声明隐藏基类方法,但部分需要隐藏的方法仅存在于std::list中。请问能否无需显式重载这些方法,通过std::enable_if语法有条件地隐藏它们?

当前实现代码

template <class ValueType, class BaseType = std::vector<ValueType>,
  std::enable_if_t<std::is_same_v<BaseType, std::vector<ValueType>> || std::is_same_v<BaseType, std::list<ValueType>>,int> = 0
>
struct Test : public BaseType
{
  Test() = default;

private:
  // 隐藏不允许直接调用的基类成员
  using BaseType::push_back;
  using BaseType::insert;
  using BaseType::assign;
  using BaseType::emplace_back;
  using BaseType::resize;
  using BaseType::swap;

  // 这些方法仅在BaseType为std::list时需要隐藏,但std::vector中不存在
  //using BaseType::merge;
  //using BaseType::push_front;
  //using BaseType::splice;
  //using BaseType::emplace_front; 
};

现有替代方案(不够优雅)

template<class T>
struct CVector : public std::vector<T>
{
    using std::vector<T>::vector;
protected:
    using std::vector<T>::assign;
    using std::vector<T>::emplace_back;
    using std::vector<T>::insert;
    using std::vector<T>::push_back;
    using std::vector<T>::resize;
    using std::vector<T>::swap;
};

template <class T>
struct CList : public std::list<T>
{
    using std::list<T>::list;
protected:
    using std::list<T>::assign;
    using std::list<T>::emplace_back;
    using std::list<T>::insert;
    using std::list<T>::push_back;
    using std::list<T>::resize;
    using std::list<T>::swap;
    using std::list<T>::emplace_front;
    using std::list<T>::merge;
    using std::list<T>::push_front;
    using std::list<T>::splice;
};

template <class ValueType, class BaseType = std::vector<ValueType>,
  std::enable_if_t<std::is_same_v<BaseType, std::vector<ValueType>> || std::is_same_v<BaseType, std::list<ValueType>>,int> = 0
>
struct Test : public std::conditional<std::is_same_v<BaseType, std::vector<ValueType>>, CVector<ValueType>, CList<ValueType>>::type
{
  Test() = default;
};
解决方案

可以通过特化辅助类或C++20条件声明实现,无需拆分包装基类,更简洁优雅:

方法一:特化混入类(兼容C++11+)

定义基础混入类处理通用隐藏逻辑,再针对std::list特化混入类补充独有方法的隐藏:

#include <vector>
#include <list>
#include <type_traits>

// 基础混入类:隐藏容器共有的修改方法
template <typename Base>
struct HideCommonMethods {
private:
    using Base::push_back;
    using Base::insert;
    using Base::assign;
    using Base::emplace_back;
    using Base::resize;
    using Base::swap;
};

// 针对std::list的特化混入类:额外隐藏list独有的方法
template <typename T>
struct HideCommonMethods<std::list<T>> : HideCommonMethods<std::vector<T>> {
private:
    using std::list<T>::merge;
    using std::list<T>::push_front;
    using std::list<T>::splice;
    using std::list<T>::emplace_front;
};

template <class ValueType, class BaseType = std::vector<ValueType>,
          std::enable_if_t<std::is_same_v<BaseType, std::vector<ValueType>> || std::is_same_v<BaseType, std::list<ValueType>>, int> = 0>
struct Test : public BaseType, private HideCommonMethods<BaseType> {
    Test() = default;
    // 按需暴露基类的安全方法,比如迭代器、大小查询等
    using BaseType::begin;
    using BaseType::end;
    using BaseType::size;
};

方法二:C++20条件using声明

利用C++20的requires从句直接在Test类内实现条件隐藏:

#include <vector>
#include <list>
#include <type_traits>

template <class ValueType, class BaseType = std::vector<ValueType>,
          std::enable_if_t<std::is_same_v<BaseType, std::vector<ValueType>> || std::is_same_v<BaseType, std::list<ValueType>>, int> = 0>
struct Test : public BaseType {
    Test() = default;

private:
    // 隐藏共有的修改方法
    using BaseType::push_back;
    using BaseType::insert;
    using BaseType::assign;
    using BaseType::emplace_back;
    using BaseType::resize;
    using BaseType::swap;

    // 条件隐藏list独有的方法:仅当BaseType是std::list时生效
    template <typename B = BaseType>
    requires std::is_same_v<B, std::list<ValueType>>
    using B::merge;

    template <typename B = BaseType>
    requires std::is_same_v<B, std::list<ValueType>>
    using B::push_front;

    template <typename B = BaseType>
    requires std::is_same_v<B, std::list<ValueType>>
    using B::splice;

    template <typename B = BaseType>
    requires std::is_same_v<B, std::list<ValueType>>
    using B::emplace_front;
};

方案说明

  • 方法一通过混入类特化复用通用逻辑,兼容较早的C++标准,避免代码重复。
  • 方法二依赖C++20特性,写法更紧凑,无需额外辅助类,直接在目标类内完成条件控制。
  • 两种方案都无需单独定义CVector/CList包装类,比原替代方案更简洁。

内容的提问来源于stack exchange,提问作者STiFU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:29:58