Zoeken…


Opmerkingen

Typekenmerken zijn sjabloonconstructies die worden gebruikt om de eigenschappen van verschillende typen tijdens het compileren te vergelijken en te testen. Ze kunnen worden gebruikt om tijdens het compileren voorwaardelijke logica te bieden die de functionaliteit van uw code op een specifieke manier kan beperken of uitbreiden. De bibliotheek met typekenmerken is ingevoerd met de standaard c++11 die een aantal verschillende functionaliteiten biedt. Het is ook mogelijk om uw eigen type vergelijkingstekens voor typen te maken.

Standaard type eigenschappen

C ++ 11

De header type_traits bevat een set sjabloonklassen en helpers om eigenschappen van typen tijdens het compileren te transformeren en te controleren.

Deze eigenschappen worden meestal in sjablonen gebruikt om te controleren op gebruikersfouten, ondersteunen generieke programmering en zorgen voor optimalisaties.


De meeste typekenmerken worden gebruikt om te controleren of een type aan enkele criteria voldoet. Deze hebben de volgende vorm:

template <class T> struct is_foo;

Als de sjabloonklasse wordt geïnstantieerd met een type dat aan een aantal criteria foo voldoet, neemt is_foo<T> van std::integral_constant<bool,true> (aka std::true_type ), anders neemt het over van std::integral_constant<bool,false> (aka std::false_type ). Dit geeft de eigenschap de volgende leden:

constanten

static constexpr bool value

true als T voldoet aan de criteria foo , anders false

functies

operator bool

Retourneert value

C ++ 14

bool operator()

Retourneert value

Types

Naam Definitie
value_type bool
type std::integral_constant<bool,value>

De eigenschap kan vervolgens worden gebruikt in constructies zoals static_assert of std::enable_if . Een voorbeeld met 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
}

Er zijn ook verschillende eigenschappen die typen transformeren, zoals std::add_pointer en std::underlying_type std::add_pointer . Deze eigenschappen onthullen over het algemeen een enkel type lidtype dat het getransformeerde type bevat. Bijvoorbeeld: std::add_pointer<int>::type is int* .

Typ relaties met std :: is_same

C ++ 11

De relatie type std::is_same<T, T> wordt gebruikt om twee typen te vergelijken. Het zal als Boolean evalueren, waar als de typen hetzelfde zijn en onwaar als anders.

bv

// 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";

De relatie type std::is_same werkt ook ongeacht typedefs. Dit wordt in het eerste voorbeeld aangetoond bij het vergelijken van int == int32_t maar dit is niet helemaal duidelijk.

bv

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

Het gebruik van std::is_same om te waarschuwen bij het onjuist gebruiken van een templated klasse of functie.

In combinatie met een statische bewering kan de sjabloon std::is_same een waardevol hulpmiddel zijn bij het afdwingen van correct gebruik van templated klassen en functies.

bijv. Een functie die alleen invoer toestaat van een int en een keuze uit twee structs.

#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;
}

Fundamentele karaktertrekken

C ++ 11

Er zijn een aantal verschillende typekenmerken die meer algemene typen vergelijken.

Is integraal:

Evalueert als waar voor alle typen gehele getallen 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.

Is drijvend punt:

Evalueert als waar voor alle drijvende komma types. 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.

Is Enum:

Evalueert als waar voor alle genoemde typen, inclusief 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.

Is aanwijzer:

Evalueert als waar voor alle wijzers.

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.

Is klasse:

Evalueert als waar voor alle klassen en struct, met uitzondering van 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.

Type eigenschappen

C ++ 11

Type-eigenschappen vergelijken de modificatoren die op verschillende variabelen kunnen worden geplaatst. Het nut van deze typekenmerken is niet altijd duidelijk.

Opmerking: het onderstaande voorbeeld biedt alleen een verbetering op een niet-optimaliserende compiler. Het is een eenvoudig proof of concept, in plaats van een complex voorbeeld.

bijv. Snel delen door vier.

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);
}

Is constant:

Dit wordt als waar geëvalueerd wanneer het type constant is.

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

Is vluchtig:

Dit wordt als waar geëvalueerd wanneer het type vluchtig is.

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

Is ondertekend:

Dit wordt als waar geëvalueerd voor alle ondertekende typen.

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.

Is niet ondertekend:

Zal evalueren als waar voor alle niet-ondertekende typen.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow