std :: applyを使用して可変長関数をタプルに適用できますか?例えばstd :: applyで可変長関数を適用する
、次のコードでは、GCC 6.2.1で正常に動作します:
void print_t(std::string i, std::string j) {
std::cout << i << " " << j << std::endl;
}
int main() {
std::tuple<std::string, std::string> t{"ab", "cd"};
std::experimental::apply(print_t, t);
return 0;
}
しかし、私は可変引数関数に適用しようとした場合:
template<typename T>
void vprint(T && t) {
std::cout << std::forward<T>(t) << std::endl;
}
template<typename T, typename ... Ts>
void vprint(T && t, Ts ... ts) {
std::cout << std::forward<T>(t) << " ";
vprint<Ts...>(std::forward<Ts>(ts)...);
}
int main() {
std::tuple<std::string, std::string> t{"fd", "ab"};
std::experimental::apply(vprint, t);
return 0;
}
をコンパイラは、テンプレートを推測することができないと文句を言い引数はvprint
です。さて、明示的に書いてみましょう:
std::experimental::apply(vprint<std::string, std::string>, t);
コンパイラは、標準ライブラリ内部を公開するいくつかのあいまいなエラーで終わります。
私はstd::apply
の独自の実装をC++ 11で書いています。なぜ私はvariadic関数テンプレートの引数を推論できないのか理解しています。しかし、の理論では、std::apply
にはその控除に必要なすべての情報があります。
GCC6ではまだ実装されていない可変機能のアプリケーションですか? C++の17互換コンパイラはこのようなアプリケーションを許可しますか? そうでなければ、vprint<std::string, std::string>
のようなインスタンス化された可変的なテンプレート関数のアプリケーションを許可しますか?
vprint<std::string, std::string>
で
なぜ第二の変形が良いですか? 'std :: move'は基本的にrvalue参照へのキャストです。したがって、両方のコードスニペットのセマンティクスは同じようです。 – Sergey
@Sergey:2番目の引数は引き続き引数を引き継ぎますが、最初の引数はタプルの型を知り、 't'を修正することができます(' print_t'はコピーによって渡されます)。 – Jarod42
@Sergey 'print_t'は呼び出したい唯一の関数ではないと仮定します。 'std :: string &&'パラメータは自由に移動できます。あなたの実装では、それから移動することはありません。意味的には、 'std :: string'を移動した後は誰も関数呼び出しに頼らざるを得ませんが、' get'のように強い保証はできません。 – Yakk