具有特定类型的完美转发



在编写线程安全的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();
}

它们几乎相同,只是采用常量l值引用和r值引用。通常我会使用完美的转发来处理这个问题(现在使用光荣的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,这样工作起来更自然。

我在多个版本中重复@Ayxan Haqverdili的示例。还要注意,因为您提到您想要一种标准的方法来解决这个,所以C++20概念现在是标准的方法。除非您正在编写需要与旧语言版本兼容的代码,否则应该使用它。主要原因是它清楚简洁地记录了申报现场的职能要求。这甚至比static_assert更有说服力,并且允许过载而不是直接故障。CCD_ 11只是一种简单的设置需求的老方法。

内联概念

template <class T>
requires std::convertible_to<T, value_type>
void push(T &&value);

自定义概念

这使您可以使用方便的参数auto

template <class T, class U>
concept ForwardType = std::convertible_to<T, U>
void push(ForwardType<value_type> auto &&value);

使用std::enable_if

这应该与C++11兼容。

template <class T>
std::enable_if_t<std::is_convertible_v<T>> push(T &&value);

最新更新