Skip to content

Type Traits

DryPerspective edited this page Oct 4, 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.

This file in particular falls victim to the lack of completeness of the Borland template engine, and some traits will be absent on Borland compilers. Where possible in code which uses these I have replaced the need for an invalid trait with an equivalent or stricter trait for Borland compilers, but it is unavoidable that some traits will be missing. Those traits are marked in the table below with an obelus†.

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

Note that dp::make_signed and dp::make_unsigned will differ from the spec on Borland compilers for wchar_t

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