Writing Custom Traits
Build your own type traits.
Writing Custom Traits is a free C++ Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the C++ Academy learning path, and your progress syncs across the web and the CoddyKit app. The C++ Academy course includes 4 lessons in total.
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+declvalpower the detection idiom- Add
_v/_thelpers and test withstatic_assert
Learn C++ with an AI tutor — free
Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.
- Courses
- 51
- Lessons
- 203
Frequently Asked Questions
Is the “Writing Custom Traits” lesson free?
Yes — any 3 lessons of the C++ Academy learning path, including “Writing Custom Traits”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The C++ Academy course includes 4 lessons in total.
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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.
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
- Querying Types
- Transforming Types
- Conditional Logic
- Writing Custom Traits