При написании поточно-ориентированной оболочки 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-значение. Обычно я бы использовал идеальную пересылку, чтобы справиться с этим (теперь использую великолепное сокращенное объявление шаблона С++ 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
или ссылкой на него, либо используйте концепцию.
static_assert
. Или вы можете просто не заморачиваться, потому чтоpush(...)
сама не скомпилируется, если тип значения неверен. - person jtbandes   schedule 27.07.2020std::is_convertible
. - person IlCapitano   schedule 27.07.2020void foo(auto&&)
— это синтаксический сахар дляtemplate <typename T> void foo(T&&)
- person NathanOliver   schedule 28.07.2020