カスタムtraitsの作成
独自の型traitsを構築します
「カスタムtraitsの作成」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
独自のトレイトを作成する
標準ライブラリに必要な問いに対応する機能がない場合は、カスタムトレイトを作成できます。トレイトとは、::valueまたは::typeを公開するテンプレートです。
プライマリテンプレートと特殊化
標準的なパターンは、falseをデフォルトとするプライマリテンプレートと、対象の型に一致して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;
}integral_constantからの継承
std::true_typeまたはstd::false_typeを継承すると、トレイトは自動的にvalueメンバーを持ち、標準トレイトと同じように動作します。
コンテナの検出
ネストされたメンバーの有無を調べることで、型がコンテナらしいかどうかを検出できます。ここでは、ヘルパーを使ってvalue_type typedefの存在に基づく特殊化を行います。
#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の解説
std::void_t<...>は、有効な型のリストをすべてvoidに変換します。内部の型のいずれかが不正な形式の場合、その特殊化はSFINAEによって除外されるため、プライマリのfalse_typeが選ばれます。
メンバー関数の検出
void_tの中で式を評価することで、型に呼び出し可能なsize()があるかどうかを検出できます。
#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>()は、未評価コンテキストで型Tの仮の値を生成します。これにより、オブジェクトを構築せずにdecltype式を記述できます。
変換トレイト
カスタムトレイトは型を生成することもできます。これはポインターの層を1つ取り除くトレイトです。
#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;
}_vと_tのヘルパーを提供する
変数テンプレートとエイリアステンプレートを追加して、標準ライブラリと同じスタイルにします。
#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;
}検出イディオム
void_tの手法は検出イディオムへと一般化されます。実験的なstd::is_detectedがこれを形式化しています。C++20のコンセプトを使うと、この処理の多くがより明瞭になります。
トレイトをテストする
static_assertでカスタムトレイトを検証すると、回帰が発生したときに直ちにビルドを失敗させることができます。
#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; }確認問題
std::void_tの役割を思い出してください。
まとめ
カスタムトレイトの作成方法を学びました。
- プライマリテンプレートはfalseをデフォルトとし、特殊化でtrueを設定します
true_type/false_typeを継承しますvoid_tとdeclvalが検出イディオムを支えます_v/_tヘルパーを追加し、static_assertでテストします
よくある質問
「カスタムtraitsの作成」レッスンは無料ですか?
はい。「カスタムtraitsの作成」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「カスタムtraitsの作成」で何を学びますか?
独自の型traitsを構築します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「カスタムtraitsの作成」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。