gpt4 book ai didi

c++ - 有没有办法在提供左值和右值重载的同时删除重复代码?

转载 作者:行者123 更新时间:2023-12-02 17:14:43 24 4
gpt4 key购买 nike

在学习 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_nodebinary_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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com