サーチ…
備考
型特性は、コンパイル時にさまざまな型のプロパティを比較してテストするために使用されるテンプレート化された構造体です。コンパイル時に特定の方法でコードの機能を制限または拡張できる条件付きロジックを提供するために使用できます。型形質ライブラリーは、いくつかの異なる機能を提供する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
bool operator()
返しvalue
タイプ
名 | 定義 |
---|---|
value_type | bool |
type | std::integral_constant<bool,value> |
この特性は、 static_assert
やstd::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_pointer
やstd::underlying_type
など、型を変換するさまざまな特性もあります。これらの特性は、一般に、変換された型を含む単一のtype
メンバ型を公開する。たとえば、 std::add_pointer<int>::type
はint*
です。
std :: is_sameとの型の関係
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;
}
基本型形質
より一般的なタイプを比較するいくつかの異なるタイプの特性があります。
インテグラル:
int
、 char
、 long
、 unsigned 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.
浮動小数点:
すべての浮動小数点型に対して真と評価します。 float
、 double
、 long 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.
タイプのプロパティ
型のプロパティは、異なる変数に配置できる修飾子を比較します。これらの型特性の有用性は必ずしも明らかではない。
注意:以下の例では、最適化されていないコンパイラのみを改善しています。複雑な例ではなく、単純な概念証明です。
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.