Skip to content

Type Traits

DryPerspective edited this page Sep 20, 2023 · 3 revisions

A recreation of the <type_traits> header in C++98. While most type traits can be implemented on the language level, there are a few features which require modern language features or compiler intrinsics. Notably is_class requires a check against is_union (a compiler intrinsic) so it and the traits which require it to work are not implemented here. Similarly, the _t and _v require using aliases and template variables respectively so could not be implemented.

In the code, you may notice some preprocessor switches such as #if !defined(__BORLANDC__) || __BORLANDC__ >= 0x0740. This is because Borland's C++98 compiler has trouble with these (perfectly valid) traits. If you are not using a Borland compiler, or are using a modern C++ version of one, these will not activate and are nothing to worry about. If you are using a compiler which disables these, the only traits whose functionality is damaged by this are make_signed and make_unsigned for wchar_t, which will fall back onto the default definition rather than following the standard-specified promotion rules for wchar_t.

Traits

integral_constant Compile-time constant of a specified type with a specified value
true_type
false_type
dp::integral_constant<bool,true>
dp::integral_constant<bool,false>
is_void Checks if a type is void
is_integral Checks if a type is an integral type
is_floating_point Checks if a type is a floating point type
is_array Checks if a type is a (C-style) array type
is_function Checks if a type is a function type
is_pointer Checks if a type is a pointer type
is_lvalue_reference Checks if a type is an lvalue reference type
is_member_object_pointer Checks if a type is a pointer to a non-static member object
is_member_function_pointer Checks if a type is a pointer to a non-static member function
is_fundamental Checks if a type is a fundamental type
is_arithmetic Checks if a type is an arithmetic type
is_compound Checks if a type is a compound type
is_reference Checks if a type is a reference type
is_member_pointer Checks if a type is a pointer to a non-static member function or object
is_const Checks if a type is const qualified
is_volatile Checks if a type is volatile qualified
is_signed Checks if a type is a signed arithmetic type
is_unsigned Checks if a type is an unsigned arithmetic type
is_bounded_array Checks if a type is a C-array of known bound
is_unbounded_array Checks if a type is a C-array of unknown bound
is_default_constructible Checks if a type can be default constructed
is_copy_constructible Checks if a type can be copy constructed
is_assignable Checks if a type can be assigned from a specific argument
is_copy_assignable Checks if a type can be copy assigned
is_destructible Checks if a type has an accessible destructor
is_swappable_with Checks if a type is swappable with another given type
is_swappable Checks if two instances of a type can be swapped
rank Obtains the number of dimensions of an array type
extent Obtains the size of an array type along a specified dimension
is_same Checks if two types are the same
is_base_of Checks if one type is derived from another type
is_convertible Checks if one type can be converted to another type
remove_const
remove_volatile
remove_cv
Removes const, volatile, and const volatile qualification from a type
add_const
add_volailte
add_cv
Adds const, volatile, and const volatile qualification to a type
remove_reference Removes reference qualification from a type
add_lvalue_reference Adds lvalue reference qualification to a type
remove_pointer Removes a pointer from the given type
add_pointer Adds a pointer to the given type
make_signed Makes the given integral type signed
make_unsigned Makes the given integral type unsigned
remove_extent Removes one extent from an array type
remove_all_extents Removes all extents from an array type
decay Performs type transformation as if passing the argument to a function by value
remove_cvref Removes const, volatile, and reference qualification from a type
enable_if Conditionally removes a function overload or template specialization from overload resolution
conditional Selects one type or another based on a compile time boolean
type_identity Returns the provided type unchanged

Sample code

#include <string>
#include <cmath>
#include "cpp98/type_traits.h"

//Function for floating points
template<typename T>
typename dp::enable_if<dp::is_floating_point<T>::value, bool>::type is_even(T in){
    return std::fmod(in, 2) == 0; //Not necessarily exact but for the sake of a simple demonstration
}

//Function for integer types
template<typname T>
typename dp::enable_if<dp::is_integral<T>::value, bool>::type is_even(T in){
    return in % 2 == 0;
}

int main(){
    int x = 100;
    double y = 45;
    std::string s = "Hello";

    is_even(x); //Selects integral overload
    is_even(y); //Selects floating point overload
    is_even(s); //Cannot select an overload. Compilation fails.
}

Clone this wiki locally