Свойства типов (type traits) и преобразования типов (type transformations) — это инструменты, предоставляемые в стандартной библиотеке C++ (в заголовке <type_traits>
), которые позволяют получать информацию о типах и выполнять преобразования типов на этапе компиляции.
- Свойства типов: Позволяют проверять характеристики типов (например, является ли тип числовым, указателем и т.д.).
- Преобразования типов: Позволяют изменять типы, например, удалять константность, добавлять ссылки и т.д.
Примеры свойств типов
Пример 1: Проверка свойств типов
#include <iostream>
#include <type_traits>
int main() {
std::cout << std::boolalpha;
std::cout << "is_integral<int>::value: " << std::is_integral<int>::value << std::endl; // true
std::cout << "is_integral<float>::value: " << std::is_integral<float>::value << std::endl; // false
std::cout << "is_pointer<int*>::value: " << std::is_pointer<int*>::value << std::endl; // true
std::cout << "is_pointer<int>::value: " << std::is_pointer<int>::value << std::endl; // false
return 0;
}
Пример 2: Условное включение кода на основе свойств типов
#include <iostream>
#include <type_traits>
// Функция работает только с указателями
template <typename T>
typename std::enable_if<std::is_pointer<T>::value, void>::type
process(T t) {
std::cout << "Processing pointer" << std::endl;
}
// Перегрузка для не указателей
template <typename T>
typename std::enable_if<!std::is_pointer<T>::value, void>::type
process(T t) {
std::cout << "Processing non-pointer" << std::endl;
}
int main() {
int x = 42;
int* p = &x;
process(x); // Processing non-pointer
process(p); // Processing pointer
return 0;
}
Примеры преобразований типов
Пример 1: Преобразование типов с удалением константности
#include <iostream>
#include <type_traits>
int main() {
using ConstInt = const int;
using NonConstInt = std::remove_const<ConstInt>::type;
std::cout << "std::is_const<ConstInt>::value: " << std::is_const<ConstInt>::value << std::endl; // true
std::cout << "std::is_const<NonConstInt>::value: " << std::is_const<NonConstInt>::value << std::endl; // false
return 0;
}
Пример 2: Добавление ссылки к типу
#include <iostream>
#include <type_traits>
int main() {
using Int = int;
using IntRef = std::add_lvalue_reference<Int>::type;
std::cout << "std::is_reference<Int>::value: " << std::is_reference<Int>::value << std::endl; // false
std::cout << "std::is_reference<IntRef>::value: " << std::is_reference<IntRef>::value << std::endl; // true
return 0;
}
Продвинутые примеры
Пример: Проверка нескольких условий с помощью SFINAE
#include <iostream>
#include <type_traits>
// Функция работает только с указателями на числовые типы
template <typename T>
typename std::enable_if<std::is_pointer<T>::value && std::is_arithmetic<typename std::remove_pointer<T>::type>::value, void>::type
process(T t) {
std::cout << "Processing pointer to arithmetic type" << std::endl;
}
int main() {
int x = 42;
int* p = &x;
float* f = nullptr;
std::string s = "Hello";
process(p); // Processing pointer to arithmetic type
process(f); // Processing pointer to arithmetic type
// process(s); // Error: No matching function for call to 'process'
return 0;
}
Пример: Преобразование типов для удаления ссылок и константности
#include <iostream>
#include <type_traits>
template <typename T>
void printTypeInfo() {
using NonConstType = typename std::remove_const<T>::type;
using NonRefType = typename std::remove_reference<NonConstType>::type;
std::cout << "Is const: " << std::is_const<T>::value << std::endl;
std::cout << "Is reference: " << std::is_reference<T>::value << std::endl;
std::cout << "Base type: " << typeid(NonRefType).name() << std::endl;
}
int main() {
printTypeInfo<const int&>(); // Is const: true, Is reference: true, Base type: int
printTypeInfo<int>(); // Is const: false, Is reference: false, Base type: int
return 0;
}