特定类型的完美转发
Perfect forwarding with a specific type
在编写线程安全 std::stack
包装器时,我为 push
进行了以下两个重载:
void push(const value_type& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(value);
_cv.notify_one();
}
void push(value_type&& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(std::move(value));
_cv.notify_one();
}
除了一个采用 const 左值引用和一个采用右值引用外,它们几乎相同。通常我会使用完美转发来处理这个(现在使用光荣的 C++20 缩写模板声明):
void push(auto&& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(std::forward<decltype(value)>(value));
_cv.notify_one();
}
这里的问题是它接受任何类型,而它应该只接受 value_type
和对它的引用。
有什么标准的方法可以解决这个问题吗?到目前为止,我想出了两种方法。要么使用 std::enable_if
以某种方式检查模板类型是否为 value_type
或对它的引用,要么使用概念。
你可以断言:
template<typename T>
void push(T&& value)
{
static_assert(is_same_v<remove_reference_t<T>, value_type>);
// ...
}
您也可以使用 is_convertible
而不是 is_same
,这样效果会更自然。
在编写线程安全 std::stack
包装器时,我为 push
进行了以下两个重载:
void push(const value_type& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(value);
_cv.notify_one();
}
void push(value_type&& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(std::move(value));
_cv.notify_one();
}
除了一个采用 const 左值引用和一个采用右值引用外,它们几乎相同。通常我会使用完美转发来处理这个(现在使用光荣的 C++20 缩写模板声明):
void push(auto&& value)
{
auto guard = std::scoped_lock{_mutex};
_stack.push(std::forward<decltype(value)>(value));
_cv.notify_one();
}
这里的问题是它接受任何类型,而它应该只接受 value_type
和对它的引用。
有什么标准的方法可以解决这个问题吗?到目前为止,我想出了两种方法。要么使用 std::enable_if
以某种方式检查模板类型是否为 value_type
或对它的引用,要么使用概念。
你可以断言:
template<typename T>
void push(T&& value)
{
static_assert(is_same_v<remove_reference_t<T>, value_type>);
// ...
}
您也可以使用 is_convertible
而不是 is_same
,这样效果会更自然。