C ++ 0xでは、テンプレートが任意の数の引数を取ることができます。タプルを実装する以外に、この機能の最適な使用法は何ですか?
8 に答える
- タイプセーフな printf
- ファクトリ メソッドでの任意の多数のコンストラクタ引数の転送
- 任意の基本クラスを持つことで、有用なポリシーを配置および削除できます。
- 可変個引数のテンプレート化されたコンストラクターを使用して、異種の型指定されたオブジェクトをコンテナーに直接移動することによる初期化。
- ユーザー定義のリテラル (「 10110b 」など) の値を計算できるリテラル演算子がある。
サンプルから 3:
template<typename... T> struct flexible : T... { flexible(): T()... { } };
サンプルから 4:
struct my_container { template<typename... T> my_container(T&&... t) { } };
my_container c = { a, b, c };
5 までのサンプル:
template<char... digits>
int operator "" b() { return convert<digits...>::value; }
このサンプル コードを参照してください:こちら
- タイプセーフ
printf
Boost.Function などで任意の数のパラメーターを使用できるようにする
複数の COM インターフェイスを実装し、C++0x 可変個引数テンプレートを使用してコードをコンパクトかつエレガントに保つ方法についての記事を書きました。
私は NDArray (N 次元配列) を実装しており、可変個の引数を持つメソッド setSizes を持っています。可変個引数のテンプレート引数を使用することは、可変個引数の関数引数を使用するよりも型安全です。さらに、可変個引数のテンプレート引数のみを使用して、コンパイル時にこの関数に渡されるパラメーターの数を制御できます。
void setSizes(uintmax_t currentSize) {
static_assert(1 == NDimensions, "Invalid count of arguments given to setSizes.");
size_ = currentSize;
data_ = new NDArrayReferenceType[currentSize];
}
template <typename... Sizes>
void setSizes(uintmax_t currentSize, Sizes... sizes) {
static_assert(sizeof...(Sizes) + 1 == NDimensions, "Invalid count of arguments given to setSizes.");
size_ = currentSize;
data_ = new NDArrayReferenceType[currentSize];
for (uintmax_t i = 0; i < currentSize; i++) {
data_[i]->setSizes(sizes...);
}
}
自作の SmartPointer 用のユニバーサル コンストラクター ラッパーも実装しました。生ポインタ型のすべてのユーザー定義コンストラクタをラップします。
template <typename TSmartPointer, typename... Args>
static inline void initialize(TSmartPointer *smartPointer, Args... args) {
smartPointer->pointer_ = new typename TSmartPointer::PointerType(std::forward<Args>(args)...);
smartPointer->__retain();
}
このコードは自明ではないようです。これは、SmartPointer (RAII) の取得時に SmartPointer がポインターのコンストラクターを自動的に呼び出す必要がある場合の SmartPointer の初期化子の一部です。抽象クラスの場合、コンストラクターを呼び出すことはできません。
したがって、抽象クラスの SmartPointer である AbstractObject 型と、2 つの int を取るコンストラクターを持つクラスの SmartPointer である ConcreteObject 型がある場合、次のコードを記述できます。
AbstractObject object = ConcreteObject(42, 42);
C# や Java (ただし RAII を使用) に似ており、C++/GCC 4.8 で動作します =)
動的引数番号を使用して、すべての呼び出しの安全性を入力します。
タイプセーフな printf は他の回答で言及されていますが、より一般的には可変個引数テンプレートを使用して、フォーマット指定子を介してタイプ情報を渡す必要のないフォーマット関数を実装できます。たとえば、C++ Format ライブラリは、Python のstr.formatに似たフォーマット関数を実装しています。
fmt::print("I'd rather be {1} than {0}.", "right", "happy");
安全なprintfに加えて。引数の型は、C++11 の可変個引数テンプレートを使用して自動的にキャプチャされます。
これにより、printf 指定子 likelld
または notoriousPRIdPTR
が不要になり、代わりに
std::printf("Local number: %" PRIdPTR "\n\n", someIntPtr);
簡単に使用できます
fmt::printf("Local number: %d\n\n", someIntPtr);
免責事項: 私はこのライブラリの作成者です