Sök…


Anmärkningar

Typegenskaper är mallkonstruktioner som används för att jämföra och testa egenskaperna hos olika typer vid sammanställningstiden. De kan användas för att tillhandahålla villkorad logik vid sammanställningstid som kan begränsa eller utöka funktionaliteten för din kod på ett specifikt sätt. Typdragsbiblioteket fördes in med c++11 standarden som ger ett antal olika funktioner. Det är också möjligt att skapa dina egna typegenskaper.

Standardtyp

C ++ 11

type_traits rubriken innehåller en uppsättning mallklasser och hjälpare för att transformera och kontrollera egenskaperna hos typer vid kompileringstid.

Dessa egenskaper används vanligtvis i mallar för att kontrollera om användarfel, stödjer generisk programmering och möjliggör optimeringar.


De flesta typdrag används för att kontrollera om en typ uppfyller vissa kriterier. Dessa har följande form:

template <class T> struct is_foo;

Om mallklassen är instanserad med en typ som uppfyller vissa kriterier foo , is_foo<T> från std::integral_constant<bool,true> (aka std::true_type ), annars ärver den från std::integral_constant<bool,false> (aka std::false_type ). Detta ger egenskaperna följande medlemmar:

Konstanter anter~~POS=HEADCOMP

static constexpr bool value

true om T uppfyller kriterierna foo , false annars

funktioner

operator bool

Returnerar value

C ++ 14

bool operator()

Returnerar value

typer

namn Definition
value_type bool
type std::integral_constant<bool,value>

Egenskapen kan sedan användas i konstruktioner som static_assert eller std::enable_if . Ett exempel med 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
}

Det finns också olika drag som omvandlar typer, såsom std::add_pointer och std::underlying_type . Dessa egenskaper exponera allmänhet en enda type medlem typ som innehåller den transformerade typen. Exempelvis är std::add_pointer<int>::type int* .

Skriv relationer med std :: is_same

C ++ 11

std::is_same<T, T> används för att jämföra två typer. Det kommer att utvärderas som booleskt, sant om typerna är desamma och falska om annat.

t.ex

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

std::is_same typ fungerar också oavsett typdefs. Detta visas faktiskt i det första exemplet när man jämför int == int32_t men detta är inte helt klart.

t.ex

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

Använd std::is_same att varna när du använder en mall eller funktion på ett felaktigt sätt.

När det kombineras med en statisk std::is_same kan std::is_same mallen vara ett värdefullt verktyg för att upprätthålla korrekt användning av mallade klasser och funktioner.

t.ex. en funktion som endast tillåter inmatning från ett int och ett val av två strukturer.

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

Grundläggande typdrag

C ++ 11

Det finns ett antal olika typdrag som jämför mer generella typer.

Är integrerad:

Utvärderar som sant för alla heltalstyper 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.

Är flytande punkt:

Utvärderar som sant för alla typer av flytande punkter. 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.

Är Enum:

Utvärderar som sant för alla uppräknade typer, inklusive 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.

Är pekaren:

Utvärderar som sant för alla pekare.

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.

Är klass:

Utvärderar som sant för alla klasser och strukturer, med undantag för 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.

Skriv egenskaper

C ++ 11

Typegenskaper jämför modifierarna som kan placeras på olika variabler. Användbarheten av dessa typdrag är inte alltid uppenbar.

Obs: Exemplet nedan skulle bara ge en förbättring av en icke-optimerande kompilator. Det är ett enkelt bevis på koncept, snarare än komplexa exempel.

t.ex. snabb dela med fyra.

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

Är konstant:

Detta kommer att utvärderas som sant när typen är konstant.

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

Är flyktig:

Detta kommer att utvärderas som sant när typen är flyktig.

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

Är undertecknad:

Detta kommer att utvärderas som sant för alla signerade typer.

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.

Är inte undertecknad:

Utvärderar som sant för alla icke signerade typer.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow