【发布时间】:2016-12-20 19:44:06
【问题描述】:
编译时,以下代码导致此错误:
'Container::Wrapper::Wrapper(S)': 成员函数已经 定义或声明
编译器是否认为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));
}
【问题讨论】:
-
“通用”引用需要使用deduced模板参数。
-
标准术语现在是转发参考。 @KerrekSB 也可以是推导出的
auto类型。 -
Wrapper(S&& obj)中的S在调用构造函数时不会推导出来,只有在定义对象Wrapper<S>时才会推导出来。因此,它是一个右值引用,而不是一个转发引用。
标签: c++ parameter-passing