質問
C ++ 0xを使用すると、テンプレートは任意の数の引数を取ることができます。タプルを実装する以外のこの機能の最適な使用方法は何ですか?
解決
- タイプセーフ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 ++フォーマットライブラリは、Pythonの str.format :
fmt::print("I'd rather be {1} than {0}.", "right", "happy");
安全なprintfに加えて。引数のタイプは、C ++ 11の可変長テンプレートを使用して自動的にキャプチャされます。
これにより、 lld
や悪名高い PRIdPTR
などのprintf指定子が不要になり、
std::printf("Local number: %" PRIdPTR "\n\n", someIntPtr);
単純に使用できます
fmt::printf("Local number: %d\n\n", someIntPtr);
免責事項:私はこのライブラリの作成者です