サーチ…


備考

型特性は、コンパイル時にさまざまな型のプロパティを比較してテストするために使用されるテンプレート化された構造体です。コンパイル時に特定の方法でコードの機能を制限または拡張できる条件付きロジックを提供するために使用できます。型形質ライブラリーは、いくつかの異なる機能を提供するc++11標準でもたらされました。独自の型形質比較テンプレートを作成することもできます。

標準型形質

C ++ 11

type_traitsヘッダーには、コンパイル時に型のプロパティを変換およびチェックするための一連のテンプレートクラスとヘルパーが含まれています。

これらの特性は、通常、ユーザーエラーをチェックし、汎用プログラミングをサポートし、最適化を可能にするためにテンプレートで使用されます。


ほとんどの型形質は、型がいくつかの基準を満たすかどうかを確認するために使用されます。これらの形式は次のとおりです。

template <class T> struct is_foo;

テンプレートクラスがいくつかの基準fooを満たす型でインスタンス化されている場合、 is_foo<T>std::integral_constant<bool,true> (別名std::true_type )から継承し、そうでなければstd::integral_constant<bool,false> (別名std::false_type )。これにより、形質には以下のメンバーが与えられます:

定数

static constexpr bool value

Tが基準fooを満たす場合はtrue 、そうでない場合はfalse

関数

operator bool

返しvalue

C ++ 14

bool operator()

返しvalue

タイプ

定義
value_type bool
type std::integral_constant<bool,value>

この特性は、 static_assertstd::enable_ifなどの構文で使用できます。 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
}

std::add_pointerstd::underlying_typeなど、型を変換するさまざまな特性もあります。これらの特性は、一般に、変換された型を含む単一のtypeメンバ型を公開する。たとえば、 std::add_pointer<int>::typeint*です。

std :: is_sameとの型の関係

C ++ 11

std::is_same<T, T>型の関係は、2つの型を比較す​​るために使用されます。ブール値として評価されます。型が同じ場合はtrue、そうでない場合はfalseです。

例えば

// 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型の関係は、typedefに関係なく動作します。これはint == int32_t比較した場合の最初の例で実際に実証されていますが、これは完全には明らかではありません。

例えば

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

テンプレート化されたクラスまたは関数を不適切に使用したときに警告するためにstd::is_sameを使用する

静的アサートと組み合わせると、 std::is_sameテンプレートは、テンプレート化されたクラスと関数の適切な使用を強制する上で貴重なツールになります。

intからの入力と2つの構造体の選択のみを許可する関数です。

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

基本型形質

C ++ 11

より一般的なタイプを比較するいくつかの異なるタイプの特性があります。

インテグラル:

intcharlongunsigned intなどのすべての整数型でtrueと評価されます。

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.

浮動小数点:

すべての浮動小数点型に対して真と評価します。 floatdoublelong doubleなど

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.

列挙型ですか?

enum classを含むすべての列挙型でtrueと評価されます。

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.

ポインタです:

すべてのポインタで真と評価します。

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.

クラスです:

enum class除いて、すべてのクラスと構造体でtrueと評価されます。

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.

タイプのプロパティ

C ++ 11

型のプロパティは、異なる変数に配置できる修飾子を比較します。これらの型特性の有用性は必ずしも明らかではない。

注意:以下の例では、最適化されていないコンパイラのみを改善しています。複雑な例ではなく、単純な概念証明です。

4倍の速さで割ります。

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

定数:

これは、型が定数のときにtrueと評価されます。

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

揮発性ですか?

タイプがvolatileのときはtrueと評価されます。

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

署名されている:

これは、すべての署名された型に対して真と評価されます。

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.

署名されていない:

すべての符号なしタイプで真と評価されます。

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
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow