Я пытаюсь сделать следующее:
struct Unwrapper
{
template<typename T>
auto operator()(const T& arg, std::enable_if_t<isPrimitive<T>, void>* = nullptr) {return arg;}
template<typename T>
auto operator()(const T& arg, std::enable_if_t<!isPrimitive<T>, void>* = nullptr) {return arg.wrapped();}
void operator()(void) {}
};
template<typename T>
using UnwrappedT = std::invoke_result_t<Unwrapper, T>; // error: no type named ‘type’ in ‘struct std::invoke_result<Unwrapper, void>’
Документы для std :: invoke_result предполагают, что он должен работать для Args
, являющегося void
(то есть ни одного), в частности, он говорит, что неработающий случай void был "причудой" ныне устаревшей std::result_of
.
Но нет, void
не работает. Это имеет смысл, потому что нельзя также сделать std::declval<T>()
для T = void
, а std::invoke_result
предполагается реализовать в терминах std::declval
.
Вопрос в том, какой самый элегантный / прямой способ исправления кода для работы с void? Я мог бы что-то сделать с std::conditional
, но я ожидал лучшего.
(с использованием C ++ 17)
Соответствующий вопрос: это , это .