Рассмотрим следующий базовый пример, основанный на void_t
:
template<typename, typename = void_t<>>
struct S: std::false_type {};
template<typename T>
struct S<T, void_t<decltype(std::declval<T>().foo())>>: std::true_type {};
Его можно использовать, как следует:
template<typename T>
std::enable_if_t<S<T>::value> func() { }
То же самое можно сделать с использованием возвращаемого возвращаемого типа и decltype
:
template<typename T>
auto func() -> decltype(std::declval<T>().foo(), void()) { }
Это верно для всех примеров, о которых я думал. Мне не удалось найти случай, в котором может использоваться либо void_t
, либо возвращаемый тип возврата с помощью decltype
, в то время как его аналог не может.
Наиболее сложные случаи могут быть решены с помощью комбинации возвращаемого типа возврата и перегрузки (в качестве примера, когда детектор используется для переключения между двумя функциями вместо триггера для отключения или включения чего-либо).
Это так? Являются ли они (void_t
и decltype
в качестве возвращаемого типа возврата плюс перегрузка при необходимости) полностью взаимозаменяемы?
В противном случае, какой случай, в котором нельзя использовать для ограничения ограничений, и я вынужден использовать определенный метод?