In this example, we are applying remove_reference_t to T directly where it’s used
This is the recommended technique when dealing with one or two short metafunctions
Type Aliases
Type aliases are really helpful when applying several metafunctions in a row
1 2 3 4 5 6 7
template <typename T> structcomplicated_metafunction { using step0 = std::make_signed_t<T>; using step1 = std::add_pointer_t<step0>; using type = std::add_cv_t<step1>; };
Variadic Templates
1 2 3 4 5 6 7 8
template <typename ... Ts> using decay_tuple = std::tuple<std::decay_t<Ts> ...>;
This technique is useful when you expect to mutate the passed strings later on in the program and you want to make the interface as simple as possible for your user
It can be easily expanded to match const char(&)[N]:
1 2 3 4 5
template <std::size_t N> struct to_std_string<const char(&)[N]> { using type = std::string; };
Summary
Learned that metafunctions are functions that operate on types
They are implemented using templates and type aliases
Understood that the Standard Library provides many metafunctions in the <type_traits> header
They can be used to check properties of types or manipulate them
Guidelines
Provide a type alias for your metafunctions in order to simplify usage syntax
decltype, std::declval<T>(), and std::is_same_v can help you implement and test your metafunctions thanks to static_assert
Use std::remove_reference_t when implementing helper make functions for classes with a perfect-forwarding constructor
Use metafunctions in the context of type deduction to streamline your interfaces and prevent surprising results