gpt4 book ai didi

c++ - 标准 :forward inside a template class

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:27:40 27 4
gpt4 key购买 nike

 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/

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