Qt:为模板(映射、列表、集合等)构建一个可变迭代器
Qt: construct a mutable iterator for template (maps, lists, sets, ...)
在我的代码中,我经常让函数在不同的可迭代Qt容器类型上做同样的事情,例如:
void removeX(QMap<qint64, QString> & map)
{
QMutableMapIterator<qint64, QString> it(map);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
void removeX(QList<QString> & list)
{
QMutableListIterator<QString> it(list);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
(我知道 QList 中已经有一个removeAll
函数。这只是一个愚蠢的最小示例)
实际代码更复杂,因此引入了大量代码重复。我宁愿有这样的东西:
template <typename T>
void removeX_(T & container)
{
typename T::mutable_iterator it(container);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
当然,这不能编译,因为Qt中根本没有"::mutable_iterator"类型定义。我看不出一个简单的方法。像"template<...>getMyMutableIterator"这样的函数在这种情况下不起作用,因为我们不允许为重载的函数返回不同的类型。
但是 C++17 中有很多新的"模板魔法",我还没有真正理解。我可以想象这可能是实现上述代码的简单方法。有没有人可以减少这里的代码重复的解决方案?
您可以定义特征模板,并部分专注于适当的容器
template <typename Container> struct q_container_traits;
template <typename T> struct q_container_traits<QList<T>>
{
using mutable_iterator = QMutableListIterator<T>;
using const_iterator = QListIterator<T>;
};
template <typename Key, typename Value> struct q_container_traits<QMap<Key, Value>>
{
using mutable_iterator = QMutableMapIterator<Key, Value>;
using const_iterator = QMapIterator<Key, Value>;
};
// etc
然后,在函数中使用q_container_traits<T>
。
template <typename T>
void removeX(T & container)
{
typename q_container_traits<T>::mutable_iterator it(container);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
您可以使用
SFINAE 禁用那些没有mutable_iterator
类型的参数T
的函数模板,使用 std::enable_if_t
和 std::is_same
template <typename T>
std::enable_if_t
<
std::is_same_v
<
typename T::mutable_iterator,
mutable_iterator
>,
void
>
removeX_(T & container)
{
typename T::mutable_iterator it(container);
while (it.hasNext()) {
it.next();
if (it.value() == "X") it.remove();
}
}
其内容如下:如果类型与 mutable_iterator
相同,则启用 void 类型作为函数的返回类型T::mutable_iterator
。如果 T 没有mutable_iterator
,则替换失败。
您可以使用type_traits
使其适应T
或其迭代器上的其他条件,例如检查它是否具有remove()
成员函数。
相关文章:
- 函数向量_指针有不同的原型,我可以构建一个吗
- 构建一个由C和C++文件组成的库
- 如何使用 samtools C API 构建一个简单的主.cpp文件
- 如何构建一个 setup.py 来编译C++使用 Python、pybind11 和 Mingw-w64 的扩展?
- 如何构建一个异常类来报告C++中的哪些文件和行号?
- 在 Visual Studio 中构建一个没有 C/C++ 运行时的静态库
- 创建一个类来访问和指定向量类型,并构建一个获取位置并为其分配区域的类
- 使用步骤c++构建一个向量
- 为什么我们需要构建一个提升库,仅仅包含头文件还不够吗,因为提升是模板
- 我正在尝试构建一个简单的程序来从 mysql 数据库中读取信息
- 构建一个真正、完全静态的Qt 5框架和应用程序(Qt 5.8之后)
- CMake 使用 ECM 构建一个库
- 如何构建一个 Map,其中键是抽象基类(而不是值)
- 从命令行构建一个.sln / .vcxproj项目,并使用Visual C 的免费版本构建
- 如果初始化需要shared_from_this,如何在一次调用中构建一个类
- 可以使用Meson构建一个琐碎的项目,但不能使用CMake
- 我如何构建一个从git克隆的单独的增强库
- 构建一个可执行文件,如果是单个 cpp 文件
- 在 Xcode 8.3 上构建一个C++正态分布式随机数生成器
- 在使用 bazel 构建一个简单的应用程序时,得到错误在 '/usr/lib/java/jdk1.8.0_74/bin/java' 找不到 java