完美转发到基类

时间:2014-12-01 04:52:18

标签: c++ c++11

#include <utility>
#include <vector>
#include <cstdint>

template <typename T>
struct Base
{
protected:
    Base(T&& data):
        data(std::forward(data)){
    }
    virtual ~Base(){};

public:

    T getData() const {return data;}

    void setData(T&& data) {
       this->data = std::forward(data);
    }
private:
    T data;
};


struct DerivedA: public Base<int>
{
public:
    DerivedA(int data):
        Base(std::move(data)){//Should I use std::forward instead of std::move here?
    }
};

struct DerivedB: public Base<const std::vector<uint16_t> >
{
public:
    DerivedB(const std::vector<uint16_t>& data):
        Base(std::move(data)){
    }
};

我的要求是在创建上面的派生类时有0次复制对象。 但无论我如何编写上面的内容,我都会遇到编译错误,这些都是最新的:

bin/Base.h: In instantiation of ‘Base<T>::Base(int, int, int, T&&) [with T = int]’:
bin/Base.h:33:82:   required from here
bin/Base.h:12:96: error: no matching function for call to ‘forward(int&)’
/usr/include/c++/4.7/bits/move.h:77:5: note: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_Tp>::type&)
/usr/include/c++/4.7/bits/move.h:77:5: note:   template argument deduction/substitution

我在这里做错了什么?

另外,我应该std::move(data) dataint中的std::forward时进行{{1}}吗?

1 个答案:

答案 0 :(得分:1)

如果你想完美地转发一个参数,你需要提供相应的三个重载或使参数成为模板参数。在任何一种情况下,当您想要使用std::forward()时,您需要指定第一个模板参数,因为它不是推导出来的。最有可能的是,你使用这样的东西:

template <typename T>
class Base {
public:
    template <typename A>
    Base(A&& data): data(std::forward<A>(data)) {}
};

std::move(data) data std::vector<uint16_t> const&时,const试图移动向量,也不会使对象看起来像非const左值:if如果要使矢量可移动,则需要将其作为非std::vector<uint16_t>&&引用,rvalue或值传递。您可能还想在std::vector<uint16_t>&std::move()上推断出类型或重载。对于这两个使用std::forward<A>(data)的重载都可以解决问题。如果您推断出类型,则会再次使用std::enable_if<...>。如果推断的类型看起来很吓人,你可以使用template <typename A> DerivedB(A&& arg, typename std::enable_if<std::is_same<typename std::decay<A>::value, std::vector<uint16_t>>::value>::type* = 0): Base(std::forward<A>(arg)) { } 使用类似的东西约束它:

{{1}}