0Pricing
C++ Academy · Lesson

Writing Custom Traits

Build your own type traits.

Writing Custom Traits is a free C++ Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Building Your Own Traits

When the standard library lacks the question you need, you can write a custom trait. A trait is simply a template that exposes ::value or ::type.

Primary Template + Specialization

The standard pattern: a primary template defaulting to false, plus a specialization that matches the type of interest and sets true.

#include <iostream>
#include <type_traits>

template <typename T>
struct is_ptr : std::false_type {};

template <typename T>
struct is_ptr<T*> : std::true_type {};

int main() {
    std::cout << is_ptr<int>::value << "\n";
    std::cout << is_ptr<int*>::value << "\n";
    return 0;
}

Inheriting from integral_constant

By inheriting from std::true_type or std::false_type, your trait automatically gets a value member and behaves like standard traits.

A Container Detector

Detect whether a type looks like a container by checking for nested members. Here we specialize on the presence of a value_type typedef via a helper.

#include <iostream>
#include <vector>
#include <type_traits>

template <typename T, typename = void>
struct has_value_type : std::false_type {};

template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};

int main() {
    std::cout << has_value_type<std::vector<int>>::value << "\n";
    std::cout << has_value_type<int>::value << "\n";
    return 0;
}

std::void_t Explained

std::void_t<...> maps any valid type list to void. If any type inside is ill-formed, the specialization is dropped via SFINAE, so the primary false_type wins.

Detecting a Member Function

You can detect whether a type has a callable size() by testing the expression in a void_t.

#include <iostream>
#include <string>
#include <type_traits>

template <typename T, typename = void>
struct has_size : std::false_type {};

template <typename T>
struct has_size<T, std::void_t<decltype(std::declval<T>().size())>> : std::true_type {};

int main() {
    std::cout << has_size<std::string>::value << "\n";
    std::cout << has_size<int>::value << "\n";
    return 0;
}

declval

std::declval<T>() produces a fake value of type T in unevaluated contexts, letting you write decltype expressions without constructing an object.

A Transform Trait

Custom traits can also produce types. This one strips a pointer layer.

#include <iostream>
#include <type_traits>

template <typename T>
struct remove_one_pointer { using type = T; };

template <typename T>
struct remove_one_pointer<T*> { using type = T; };

int main() {
    using R = remove_one_pointer<int*>::type;
    std::cout << std::is_same_v<R, int> << "\n";
    return 0;
}

Providing _v and _t Helpers

Match the standard style by adding variable and alias templates.

#include <iostream>
#include <type_traits>

template <typename T>
struct is_char : std::false_type {};
template <>
struct is_char<char> : std::true_type {};

template <typename T>
inline constexpr bool is_char_v = is_char<T>::value;

int main() {
    std::cout << is_char_v<char> << "\n";
    std::cout << is_char_v<int> << "\n";
    return 0;
}

Detection Idiom

The void_t technique generalizes into the detection idiom, which the experimental std::is_detected formalizes. C++20 concepts make much of this cleaner.

Testing Your Traits

Verify custom traits with static_assert so any regression breaks the build immediately.

#include <type_traits>

template <typename T>
struct is_void_like : std::false_type {};
template <>
struct is_void_like<void> : std::true_type {};

static_assert(is_void_like<void>::value);
static_assert(!is_void_like<int>::value);

int main() { return 0; }

Quick Check

Recall the role of std::void_t.

Recap

You learned to write custom traits.

  • Primary template defaults false; specialization sets true
  • Inherit from true_type/false_type
  • void_t + declval power the detection idiom
  • Add _v/_t helpers and test with static_assert

Frequently asked questions

Is the “Writing Custom Traits” lesson free?

Yes — the full text of “Writing Custom Traits” is free to read here on the web, and the C++ Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C++ Academy course, upgrade to CoddyKit PRO.

What will I learn in “Writing Custom Traits”?

Build your own type traits. You practise C++ Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C++ Academy?

No prior experience is required. C++ Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Writing Custom Traits” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C++ Academy lesson?

Yes. Every C++ Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Querying Types
  2. Transforming Types
  3. Conditional Logic
  4. Writing Custom Traits
← Back to C++ Academy