gpt4 book ai didi

c++ - 如何在非泛型上实现完美转发?

转载 作者:行者123 更新时间:2023-11-30 01:46:34 27 4
gpt4 key购买 nike

假设我有以下代码:

class Element;
typedef shared_ptr<Element> ElementPtr;

class Element
{
public:
void add_child(const ElementPtr& elem);

private:
vector<ElementPtr> children;
}

inline void Element::add_child(const ElementPtr& elem)
{
children.push_back(elem);
};

我想更新 add_child 以使用完美转发。我尝试更改函数定义(和声明),因此使用以下逻辑:

void Element::add_child(ElementPtr&& elem)
{
children.push_back(forward<ElementPtr>(elem));
}

但是对于参数 elem 是左值的任何调用,这会崩溃。所以我想我会尝试使用模板并提出以下建议:

template <ElementPtr elem>
void Element::add_child(ElementPtr&& elem)
{
children.push_back(forward<ElementPtr>(elem));
}

...但这无法编译。所以我把它改成这样:

template <class T>
void Element::add_child(T&& elem)
{
children.push_back(forward<T>(elem));
}

...编译并工作,但看起来丑陋且不合适; add_child 只会接受类型为 ElementPtr 的参数,那么它的函数声明不应该反射(reflect)这一点吗?

有什么方法可以实现一个函数的完美转发,同时在语法上证明它只接受一种变量?我基本上想要一个可以自动区分特定参数类型的左值和右值版本的函数。

最佳答案

你的选择是

  1. 使用两个重载(又名“vector::push_back 做什么”):

    void add_child(const ElementPtr& elem) { children.push_back(elem); }
    void add_child(ElementPtr&& elem) { children.push_back(std::move(elem)); }
  2. 使用按值获取其参数的单个重载:

    void add_child(ElementPtr elem) { children.push_back(std::move(elem)); }
  3. SFINAE.

    template <class T,
    class = std::enable_if_t<std::is_same<ElementPtr, std::decay_t<T>>{}>>
    void Element::add_child(T&& elem)
    {
    children.push_back(forward<T>(elem));
    }

选项 2 最多花费一次额外的 move ,但是 move shared_ptr 很便宜,因为您不需要触及引用计数。选项 1 是有效的,但受组合爆炸的影响。选项 3 也很有效,但更难阅读和维护。

关于c++ - 如何在非泛型上实现完美转发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32960020/

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