std:: void_t
| Type traits | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time rational arithmetic | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Compile-time integer sequences | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(C++14)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Défini dans l'en-tête
<type_traits>
|
||
|
template
<
class
...
>
using void_t = void ; |
(depuis C++17) | |
Métafonction utilitaire qui transforme une séquence de types quelconques en le type void . Cette métafonction est un moyen pratique d'exploiter SFINAE avant les concepts de C++20, en particulier pour supprimer conditionnellement des fonctions de l' ensemble des candidats selon qu'une expression est valide dans le contexte non évalué (tel qu'un opérande d'une expression decltype ), permettant ainsi l'existence de surcharges de fonctions ou de spécialisations distinctes basées sur les opérations supportées.
Notes
Cette métafonction est utilisée en métaprogrammation de modèles pour détecter les types mal formés dans un contexte SFINAE :
// le modèle primaire gère les types qui n'ont pas de membre ::type imbriqué : template<class, class = void> struct has_type_member : std::false_type {}; // la spécialisation reconnaît les types qui ont un membre ::type imbriqué : template<class T> struct has_type_member<T, std::void_t<typename T::type>> : std::true_type {};
Il peut également être utilisé pour détecter la validité d'une expression :
// le modèle principal gère les types qui ne supportent pas le pré-incrément : template<class, class = void> struct has_pre_increment_member : std::false_type {}; // la spécialisation reconnaît les types qui supportent le pré-incrément : template<class T> struct has_pre_increment_member<T, std::void_t<decltype(++std::declval<T&>())> > : std::true_type {};
Jusqu'à la résolution de
CWG issue 1558
(un défaut de C++11), les paramètres inutilisés dans les
alias templates
n'étaient pas garantis d'assurer SFINAE et pouvaient être ignorés, donc les compilateurs antérieurs nécessitent une définition plus complexe de
void_t
, telle que
template<typename... Ts> struct make_void { typedef void type; }; template<typename... Ts> using void_t = typename make_void<Ts...>::type;
| Macro de test de fonctionnalité | Valeur | Std | Fonctionnalité |
|---|---|---|---|
__cpp_lib_void_t
|
201411L
|
(C++17) |
std::void_t
|
Exemple
#include <iomanip> #include <iostream> #include <map> #include <type_traits> #include <vector> // Variable template qui vérifie si un type possède des fonctions membres begin() et 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 trait d'itérateur dont le value_type est le value_type du conteneur itéré, // prend en charge même back_insert_iterator (où value_type est 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>); }
Sortie :
is_range<std::vector<double>> == true is_range<std::map<int, double>> == true is_range<double> == false is_range<A> == false
Voir aussi
|
(C++11)
|
supprime conditionnellement
une surcharge de fonction
ou une spécialisation de modèle de la résolution de surcharge
(modèle de classe) |