c++ - && 什么时候表示 'forwarding reference' ?

标签 c++ parameter-passing

编译时,以下代码会导致此错误:

'Container::Wrapper::Wrapper(S)': member function already defined or declared

编译器是否认为Wrapper的构造函数中的S&&是转发引用?

template<typename T>
struct Container
{
    template<class S>
    struct Wrapper {
        S obj;
        Wrapper(S&& obj) : obj(std::forward<S>(obj)){}
        Wrapper(const S& obj) : obj(obj){}
    };

    template<class S>
    void push_back(S&& obj) {
        void *storage = malloc(sizeof(Wrapper<S>));
        new (storage) Wrapper<S>(std::forward<S>(obj));
    }
};

struct Foobar{};

int main()
{
    Container<Foobar> cont;
    Foobar foobar;
    cont.push_back(foobar);
    return 0;
}

查看 here 中的示例,我不明白我在做什么有什么不同:

template <class T, class Allocator = allocator<T> >
class vector {
public:
    ...
    void push_back(T&& x);       // fully specified parameter type ⇒ no type deduction;
    ...                          // && ≡ rvalue reference
};


编辑: 此问题的解决方案是修改 push_back 以从用于实例化 Wrapper 的类型中删除引用:

template<class S>
void push_back(S&& obj) {
    typedef std::remove_reference<S>::type U;
    void *storage = malloc(sizeof(Wrapper<U>));
    new (storage) Wrapper<U>(std::forward<S>(obj));
}

最佳答案

Wrapper 的实现没有涉及通用引用。 .您代码中唯一的通用引用是 Container<>::push_back的参数。

当您调用 cont.push_back(foobar); 时, 参数 Spush_back推导为 Foobar & .

稍后您尝试实例化您的 Wrapper<S>S == Foobar & .引用折叠规则规定在 Wrapper的构造函数参数声明 S &&变成 Foobar &const S &也变成了Foobar & .

这意味着您最终得到两个所谓的“重载”Wrapper::Wrapper具有相同签名的构造函数。这就是您观察到的错误消息的原因。

如果您尝试实例化 std::vector使用左值引用类型的模板参数,您将遇到与它的 push_back 完全相同的问题。过载。然而,在达到 push_back 之前,这样的尝试编译通常会由于其他原因而惨败。过载。

一个更精炼的例子如下所示

template <typename T> struct MyVector {
  void foo(T &&) {}
  void foo(const T &) {}
};

int main() {
  MyVector<int &> v;
}

并且会产生同样的错误。

这里相当不明显的部分是 const T &T = U &实际上变成了U &而不是 const U & .但事实确实如此。

关于c++ - && 什么时候表示 'forwarding reference' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41250100/

相关文章:

c++ - alDeleteBuffers 函数的“名称无效”错误

不同文件中的 C++ 类问题

C++ 复制指针指向的数据

flutter - 将值传递给要在底部工作表中使用的 float 操作按钮

amazon-web-services - AWS CloudFormation CodePipeline、ParameterOverrides、将列表传递到嵌套堆栈

java - 如何在方法之间正确传递数组

javascript - 如何传递原型(prototype)函数并在 JavaScript 中使用

c++ - 在类中包装 Windows 句柄

c++ - 我如何为此二进制搜索函数创建具有修改后的最大/最小值的新数组

c - 将结构传递给接受 void * 参数的函数的问题