- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在学习 C++ 时,我决定编写一个简单的模板化二叉搜索树 (bst),并遇到了以下问题:我希望能够通过传递像 这样的左值来构造 bst >const T &val
和类似 T &&val
的右值。同样,我希望能够插入左值和右值。所以我最终得到了很多我不喜欢的重复代码:
/// copy constructor
explicit inline constexpr binary_search_tree(const T &val)
: _root{std::make_unique<binary_search_tree_node>(val)} {}
/// move constructor
explicit inline constexpr binary_search_tree(T &&val)
: _root{std::make_unique<binary_search_tree_node>(std::move(val))} {}
对于构造函数,其中 binary_search_tree_node
是 binary_search_tree
的私有(private)成员,然后它还必须提供复制和移动构造函数:
struct binary_search_tree_node {
T value;
std::unique_ptr<binary_search_tree_node> left;
std::unique_ptr<binary_search_tree_node> right;
// prohibit creation of tree_node without value
inline constexpr binary_search_tree_node() = delete;
/// copy constructor
explicit inline constexpr binary_search_tree_node(const T &val)
: value{val}, left{nullptr}, right{nullptr} {}
/// move constructor
explicit inline constexpr binary_search_tree_node(T &&val)
: value{std::move(val)}, left{nullptr}, right{nullptr} {}
};
另外:
inline constexpr void insert(const T &v) {
if (!_root) {
_root = std::make_unique<binary_search_tree_node>(v);
++_size;
} else {
insert(_root, v);
}
}
inline constexpr void insert(T &&v) {
if (!_root) {
_root = std::make_unique<binary_search_tree_node>(std::move(v));
++_size;
} else {
insert(_root, std::move(v));
}
}
用于插入功能。
当我想要搜索一个值时,这个列表还在继续:我是否应该为 find(const T &val)
和 find(T &&val)< 提供重载
..?
So my question is whether there is a way of combining these overloads or any other way to remove this duplicate code?
我读到了reference collapsing rules但我不确定我是否可以在这里利用这个概念。
任何其他想法或建议也表示赞赏。
最佳答案
是的,您可以使用引用折叠来减少编写的函数量。
例如,您的函数插入可以使用右值引用+立即上下文来利用引用折叠,从而产生转发引用:
template<typename U>
inline constexpr void insert(U &&v) { // v is a forwarding reference
if (!_root) {
// we use std::forward to keep rvalue-ness
// of the named object when v is an rvalue, but not when it's a lvalue
_root = std::make_unique<binary_search_tree_node>(std::forward<U>(v));
++_size;
} else {
insert(_root, std::forward<U>(v));
}
}
即使参数使用右值引用,由于引用崩溃,左值也将在这里工作。如果 U
推导为 int&
,则该参数是 int& &&
类型,它会折叠为 int&
。相反,如果发送右值,则会将 int
推导为 U
,因此参数为 int &&
。
这种模式称为转发引用。
如您所见,只有当转发参数存在模板参数推导时,此类代码才具有该属性。
请注意,如果没有正确约束,将其设为模板将使其接受比预期更多的类型。
您还可以使用拷贝然后移动以避免代码重复:
inline constexpr void insert(const T &v) {
T copy = v;
insert(std::move(copy)); // calls the rvalue overload
}
关于c++ - 有没有办法在提供左值和右值重载的同时删除重复代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60288434/
我是一名优秀的程序员,十分优秀!