作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
template<typename T>
class BlockingQueue
{
std::queue<T> container_;
template< typename U >
void push(U&& value)
{
static_assert(std::is_same<T, typename std::remove_reference<U>::type>::value,"Can't call push without the same parameter as template parameter's class");
container_.push(std::forward<U>(value));
}
};
我希望 BlockingQueue::push 方法能够处理 T 类型对象的右值和左值引用,以将其转发到 std::queue::push
正确的版本。是像上面的代码那样做,还是在我的 BlockingQueue
类中提供两个版本的 push 方法更好?一个用于左值,一个用于右值
最佳答案
对我来说,实现似乎是正确的,并且可以完成工作。
不过,在您的情况下,为左值和右值提供不同的实现可能是个好主意。主要原因(我能想到的)是模板类型参数的推导不适用于braced-init-lists。考虑:
struct foo {
foo(std::initializer_list<int>) {
}
};
// ...
foo f{1, 2, 3}; // OK
BlockingQueue<foo> b;
使用 OP 的代码 (*)
b.push(f); // OK
b.push({1, 2, 3}); // Error
如果相反,提供以下 BlockingQueue::push
重载:
void push(const T& value) {
container_.push(value);
}
void push(T&& value) {
container_.push(std::move(value));
}
那么过去失败的线路将正常工作。
相同的论点适用于聚合。例如,如果 foo
定义为
struct foo {
int a, b, c;
};
人们会观察到上述相同的行为。
我的结论是,如果您希望 BlockingQueue
支持更多类型(包括聚合或构造函数采用 std::initializer_list
的类型),那么最好提供两种不同的重载。
(*) OP 代码中的一个小修正:在 static_assert
中你需要使用 typename
typename std::remove_reference<U>::type>::value
^^^^^^^^
关于c++ - 标准 :forward inside a template class,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19723754/
我是一名优秀的程序员,十分优秀!