std:: void_t
| Type traits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time rational arithmetic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time integer sequences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(C++14)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Definido en el encabezado
<type_traits>
|
||
|
template
<
class
...
>
using void_t = void ; |
(desde C++17) | |
Metafunción de utilidad que mapea una secuencia de cualquier tipo al tipo void . Esta metafunción es una forma conveniente de aprovechar SFINAE antes de los conceptos de C++20, en particular para eliminar condicionalmente funciones del conjunto de candidatos basándose en si una expresión es válida en el contexto no evaluado (como operando de una expresión decltype ), permitiendo que existan sobrecargas de funciones o especializaciones separadas basadas en operaciones soportadas.
Notas
Esta metafunción se utiliza en metaprogramación de plantillas para detectar tipos mal formados en contexto SFINAE:
// la plantilla principal maneja tipos que no tienen un miembro ::type anidado: template<class, class = void> struct has_type_member : std::false_type {}; // la especialización reconoce tipos que sí tienen un miembro ::type anidado: template<class T> struct has_type_member<T, std::void_t<typename T::type>> : std::true_type {};
También puede utilizarse para detectar la validez de una expresión:
// la plantilla primaria maneja tipos que no admiten pre-incremento: template<class, class = void> struct has_pre_increment_member : std::false_type {}; // la especialización reconoce tipos que sí admiten pre-incremento: template<class T> struct has_pre_increment_member<T, std::void_t<decltype(++std::declval<T&>())> > : std::true_type {};
Hasta la resolución de
CWG issue 1558
(un defecto de C++11), los parámetros no utilizados en
alias templates
no garantizaban SFINAE y podían ser ignorados, por lo que los compiladores anteriores requieren una definición más compleja de
void_t
, como
template<typename... Ts> struct make_void { typedef void type; }; template<typename... Ts> using void_t = typename make_void<Ts...>::type;
| Macro de prueba de características | Valor | Estándar | Característica |
|---|---|---|---|
__cpp_lib_void_t
|
201411L
|
(C++17) |
std::void_t
|
Ejemplo
#include <iomanip> #include <iostream> #include <map> #include <type_traits> #include <vector> // Variable template que verifica si un tipo tiene funciones miembro begin() y end() template<typename, typename = void> constexpr bool is_range = false; template<typename T> constexpr bool is_range<T, std::void_t<decltype(std::declval<T>().begin()), decltype(std::declval<T>().end())>> = true; // Un rasgo de iterador cuyo value_type es el value_type del contenedor iterado, // admite incluso back_insert_iterator (donde value_type es void) template<typename T, typename = void> struct iterator_trait : std::iterator_traits<T> {}; template<typename T> struct iterator_trait<T, std::void_t<typename T::container_type>> : std::iterator_traits<typename T::container_type::iterator> {}; class A {}; #define SHOW(...) std::cout << std::setw(34) << #__VA_ARGS__ \ << " == " << __VA_ARGS__ << '\n' int main() { std::cout << std::boolalpha << std::left; SHOW(is_range<std::vector<double>>); SHOW(is_range<std::map<int, double>>); SHOW(is_range<double>); SHOW(is_range<A>); using container_t = std::vector<int>; container_t v; static_assert(std::is_same_v< container_t::value_type, iterator_trait<decltype(std::begin(v))>::value_type>); static_assert(std::is_same_v< container_t::value_type, iterator_trait<decltype(std::back_inserter(v))>::value_type>); }
Salida:
is_range<std::vector<double>> == true is_range<std::map<int, double>> == true is_range<double> == false is_range<A> == false
Véase también
|
(C++11)
|
elimina condicionalmente
una sobrecarga de función
o especialización de plantilla de la resolución de sobrecarga
(plantilla de clase) |