特定类型的完美转发

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,这样效果会更自然。