Recherche…


Remarques

Les traits de type sont des constructions basées sur des modèles utilisées pour comparer et tester les propriétés de différents types au moment de la compilation. Ils peuvent être utilisés pour fournir une logique conditionnelle au moment de la compilation qui peut limiter ou étendre les fonctionnalités de votre code de manière spécifique. La bibliothèque de caractères de type a été introduite avec le standard c++11 qui fournit un certain nombre de fonctionnalités différentes. Il est également possible de créer vos propres modèles de comparaison de caractères.

Traits de type standard

C ++ 11

L'en type_traits tête type_traits contient un ensemble de classes de modèles et de helpers pour transformer et vérifier les propriétés des types au moment de la compilation.

Ces traits sont généralement utilisés dans les modèles pour vérifier les erreurs des utilisateurs, prendre en charge la programmation générique et permettre des optimisations.


La plupart des caractères sont utilisés pour vérifier si un type remplit certains critères. Ceux-ci ont la forme suivante:

template <class T> struct is_foo;

Si la classe de modèle est instancié avec un type qui répond à certains critères foo , puis is_foo<T> hérite de std::integral_constant<bool,true> (alias std::true_type ), sinon il hérite de std::integral_constant<bool,false> (aka std::false_type ). Cela donne le trait aux membres suivants:

Les constantes

static constexpr bool value

true si T remplit les critères foo , false sinon

Les fonctions

operator bool

Renvoie la value

C ++ 14

bool operator()

Renvoie la value

Les types

prénom Définition
value_type bool
type std::integral_constant<bool,value>

Le trait peut ensuite être utilisé dans des constructions telles que static_assert ou std::enable_if . Un exemple avec std::is_pointer :

template <typename T>
void i_require_a_pointer (T t) {
    static_assert(std::is_pointer<T>::value, "T must be a pointer type");
}

//Overload for when T is not a pointer type
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value>::type
does_something_special_with_pointer (T t) {
    //Do something boring
}

//Overload for when T is a pointer type
template <typename T>
typename std::enable_if<std::is_pointer<T>::value>::type 
does_something_special_with_pointer (T t) {
    //Do something special
}

Il existe également divers traits qui transforment les types, tels que std::add_pointer et std::underlying_type std::add_pointer std::underlying_type . Ces traits exposent généralement un type membre de type unique qui contient le type transformé. Par exemple, std::add_pointer<int>::type est int* .

Tapez les relations avec std :: is_same

C ++ 11

La relation de type std::is_same<T, T> est utilisée pour comparer deux types. Il évaluera comme booléen, true si les types sont les mêmes et faux si autrement.

par exemple

// Prints true on most x86 and x86_64 compilers.
std::cout << std::is_same<int, int32_t>::value << "\n";
// Prints false on all compilers.
std::cout << std::is_same<float, int>::value << "\n";
// Prints false on all compilers.
std::cout  << std::is_same<unsigned int, int>::value << "\n";

La relation de type std::is_same fonctionnera également indépendamment des typedefs. Ceci est en fait démontré dans le premier exemple en comparant int == int32_t mais ce n'est pas tout à fait clair.

par exemple

// Prints true on all compilers.
typedef int MyType
std::cout << std::is_same<int, MyType>::value <<  "\n";

Utiliser std::is_same pour avertir lorsque vous utilisez incorrectement une classe ou une fonction std::is_same sur un modèle.

Lorsqu'il est associé à une affirmation statique, le modèle std::is_same peut être un outil précieux pour std::is_same utilisation correcte des classes et des fonctions std::is_same modèles.

Par exemple, une fonction qui n'autorise que les entrées d'un int et un choix de deux structures.

#include <type_traits>
struct foo {
  int member;
  // Other variables
};

struct bar {
  char member;
};

template<typename T>
int AddStructMember(T var1, int var2) {
  // If type T != foo || T != bar then show error message.
  static_assert(std::is_same<T, foo>::value || 
    std::is_same<T, bar>::value,
    "This function does not support the specified type.");
  return var1.member + var2;
}

Traits de type fondamentaux

C ++ 11

Il existe un certain nombre de caractères différents qui comparent des types plus généraux.

Est intégral:

Evalue comme vrai pour tous les types entiers int , char , long , unsigned int etc.

std::cout << std::is_integral<int>::value << "\n"; // Prints true.
std::cout << std::is_integral<char>::value << "\n"; // Prints true.
std::cout << std::is_integral<float>::value << "\n"; // Prints false.

Est Flottant Point:

Évalue comme vrai pour tous les types à virgule flottante. float , double , long double etc.

std::cout << std::is_floating_point<float>::value << "\n"; // Prints true.
std::cout << std::is_floating_point<double>::value << "\n"; // Prints true.
std::cout << std::is_floating_point<char>::value << "\n"; // Prints false.

Est Enum:

Évalue comme vrai pour tous les types énumérés, y compris la enum class .

enum fruit {apple, pair, banana};
enum class vegetable {carrot, spinach, leek};
std::cout << std::is_enum<fruit>::value << "\n"; // Prints true.
std::cout << std::is_enum<vegetable>::value << "\n"; // Prints true.
std::cout << std::is_enum<int>::value << "\n"; // Prints false.

Est le pointeur:

Évalue comme vrai pour tous les pointeurs.

std::cout << std::is_pointer<int *>::value << "\n"; // Prints true.
typedef int* MyPTR;
std::cout << std::is_pointer<MyPTR>::value << "\n"; // Prints true.
std::cout << std::is_pointer<int>::value << "\n"; // Prints false.

Est classe:

Evalue comme vrai pour toutes les classes et struct, à l'exception de la enum class .

struct FOO {int x, y;};
class BAR {
 public:
  int x, y;
};
enum class fruit {apple, pair, banana};
std::cout << std::is_class<FOO>::value << "\n"; // Prints true.
std::cout << std::is_class<BAR>::value << "\n"; // Prints true.
std::cout << std::is_class<fruit>::value << "\n"; // Prints false.
std::cout << std::is_class<int>::value << "\n"; // Prints false.

Propriétés du type

C ++ 11

Les propriétés de type comparent les modificateurs pouvant être placés sur différentes variables. L'utilité de ces caractères de type n'est pas toujours évidente.

Remarque: L'exemple ci-dessous n'offre qu'une amélioration sur un compilateur non optimisé. C'est un simple exemple de preuve de concept, plutôt qu'un exemple complexe.

Par exemple, diviser rapidement par quatre.

template<typename T>
inline T FastDivideByFour(cont T &var) {
  // Will give an error if the inputted type is not an unsigned integral type.    
  static_assert(std::is_unsigned<T>::value && std::is_integral<T>::value,
    "This function is only designed for unsigned integral types.");
  return (var >> 2);
}

Est constante:

Cela sera considéré comme vrai lorsque le type est constant.

std::cout << std::is_const<const int>::value << "\n"; // Prints true.
std::cout << std::is_const<int>::value << "\n"; // Prints false.

Est volatile:

Cela sera évalué comme vrai lorsque le type est volatile.

std::cout << std::is_volatile<static volatile int>::value << "\n"; // Prints true.
std::cout << std::is_const<const int>::value << "\n"; // Prints false.

Est signé:

Cela sera considéré comme vrai pour tous les types signés.

std::cout << std::is_signed<int>::value << "\n"; // Prints true.
std::cout << std::is_signed<float>::value << "\n"; // Prints true.
std::cout << std::is_signed<unsigned int>::value << "\n"; // Prints false.
std::cout << std::is_signed<uint8_t>::value << "\n"; // Prints false.

Est non signé:

Sera évalué comme vrai pour tous les types non signés.

std::cout << std::is_unsigned<unsigned int>::value << "\n"; // Prints true.
std::cout << std::is_signed<uint8_t>::value << "\n"; // Prints true.
std::cout << std::is_unsigned<int>::value << "\n"; // Prints false.
std::cout << std::is_signed<float>::value << "\n"; // Prints false.


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow