[解決済み] 可変個体テンプレートにおける「...」トークンのルールとは?
質問
C++11では、このような変種テンプレートがあります。
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
これにはいくつかの不思議な点があります。この式は
std::forward<Args>(args)...
という表現では
Args
と
args
が、1つだけ
...
トークンだけです。さらに
std::forward
は1つのテンプレートパラメータと1つの引数だけを取る非変数テンプレート関数です。そのための構文規則は(おおよそ)何でしょうか?それはどのように一般化することができますか?
また 関数の実装では、省略記号 (
...
) は、関心のある表現の最後にあります。テンプレートの引数リストとパラメータリストでは省略記号が真ん中になっていますが、何か理由があるのでしょうか?
どのように解決すればよいですか?
variadic テンプレートのコンテキストでは、省略記号の
...
は、テンプレートパラメータパックが式の右側に現れる場合、それを展開するために使われます(この式を呼び出します
パターン
に現れる場合はpackの引数として使われます。
左
側に表示される場合は pack 引数です。
...thing // pack : appears as template arguments
thing... // unpack : appears when consuming the arguments
このルールは、どんな
パターン
の左側にある
...
が繰り返される - パックされていないパターン(それらを
表現
と呼びます) はカンマで区切られ
,
.
これはいくつかの例によって最もよく理解することができます。このような関数テンプレートがあるとします。
template<typename ...T> //pack
void f(T ... args) //pack
{
// here are unpack patterns
g( args... ); //pattern = args
h( x(args)... ); //pattern = x(args)
m( y(args...) ); //pattern = args (as argument to y())
n( z<T>(args)... ); //pattern = z<T>(args)
}
ここで、この関数に
T
として
{int, char, short}
とすると、各関数呼び出しは次のように展開されます。
g( arg0, arg1, arg2 );
h( x(arg0), x(arg1), x(arg2) );
m( y(arg0, arg1, arg2) );
n( z<int>(arg0), z<char>(arg1), z<short>(arg2) );
投稿されたコードで
std::forward
が示す4番目のパターンに従って
n()
関数呼び出しで示される4番目のパターンに従います。
との違いに注意してください。
x(args)...
と
y(args...)
の上にあります!
この場合
...
としても、配列を初期化することができます。
struct data_info
{
boost::any data;
std::size_t type_size;
};
std::vector<data_info> v{{args, sizeof(T)}...}; //pattern = {args, sizeof(T)}
というように展開されます。
std::vector<data_info> v
{
{arg0, sizeof(int)},
{arg1, sizeof(char)},
{arg2, sizeof(short)}
};
今気づいたのですが、パターンには以下のようなアクセス指定子を含めることもできます。
public
のようなアクセス指定子を含むことができることに気づきました。
template<typename ... Mixins>
struct mixture : public Mixins ... //pattern = public Mixins
{
//code
};
この例では、このパターンは次のように展開されます。
struct mixture__instantiated : public Mixin0, public Mixin1, .. public MixinN
ということです。
mixture
が導き出す
公的に
を全ての基本クラスから派生させます。
お役に立てれば幸いです。
関連
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] なぜテンプレートはヘッダーファイルでしか実装できないのですか?
-
[解決済み] ベースクラスのコンストラクタを呼び出す際のルールは?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 unsigned int vs. size_t
-
[解決済み】非静的メンバ関数への参照を呼び出す必要がある
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】Cygwin Make bash コマンドが見つかりません。
-
[解決済み】テンプレートの引数1が無効です(Code::Blocks Win Vista) - テンプレートは使いません。
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】クラステンプレートの使用にはテンプレート引数リストが必要です
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み] 解決済み] `pthread_create' への未定義の参照 [重複] [重複