これは動作します
C ++ 11をいじって、任意のオブジェクトをに書き込むことで、それらを連結する関数を作成しようとしましたostringstream
。それらのヘルパー関数として、既存のアイテムに単一のアイテムを追加する可変個引数ヘルパー関数がありますostream
(以下の完全な貼り付けでより多くのコンテキストが示されています)。
template<class Head, class... Tail>
std::ostream& append(std::ostream& out, const Head& head, const Tail&... tail)
{
return append(out << head, tail...);
}
これは失敗します
<<
しかし、ストリームに適用すると、ostreamではなく、プレースホルダーを返すオブジェクトがあるのではないかと思いました。したがって、ストリームにテンプレート引数も入力させると便利です。
1 #include <iostream>
2 #include <sstream>
3
4 template<typename Stream>
5 Stream& append(Stream& out) {
6 return out;
7 }
8
9 template<class Stream, class Head, class... Tail>
10 auto append(Stream& out, const Head& head, const Tail&... tail)
11 -> decltype(append(out << head, tail...)) // <<<<< This is the important line!
12 {
13 return append(out << head, tail...);
14 }
15
16 template<class... Args>
17 std::string concat(const Args&... args) {
18 std::ostringstream s;
19 append(s, args...);
20 return s.str();
21 }
22
23 int main() {
24 std::cout << concat("foo ", 3, " bar ", 7) << std::endl;
25 }
しかし、g++-4.7.1
これをコンパイルすることを拒否します。
Stream
シグニチャののすべての使用法を元に戻してstd::ostream
も、それは改善されないため、gccが4.4以降サポートしていると主張していても、ここでは新しい関数宣言構文が主要な役割を果たしていると思います。
エラーメッセージ
エラーメッセージはかなり不可解であり、ここで何が起こっているのかを教えてくれません。しかし、おそらくあなたはそれを理解することができます。
In instantiation of ‘std::string concat(const Args& ...) [with Args = {char [5], int, char [6], int}; std::string = std::basic_string<char>]’:
24:44: required from here
19:3: error: no matching function for call to ‘append(std::ostringstream&, const char [5], const int&, const char [6], const int&)’
19:3: note: candidates are:
5:9: note: template<class Stream> Stream& append(Stream&)
5:9: note: template argument deduction/substitution failed:
19:3: note: candidate expects 1 argument, 5 provided
10:6: note: template<class Stream, class Head, class ... Tail> decltype (append((out << head), append::tail ...)) append(Stream&, const Head&, const Tail& ...)
10:6: note: template argument deduction/substitution failed:
In substitution of ‘template<class Stream, class Head, class ... Tail> decltype (append((out << head), tail ...)) append(Stream&, const Head&, const Tail& ...) [with Stream = std::basic_ostringstream<char>; Head = char [5]; Tail = {int, char [6], int}]’:
19:3: required from ‘std::string concat(const Args& ...) [with Args = {char [5], int, char [6], int}; std::string = std::basic_string<char>]’
24:44: required from here
10:6: error: no matching function for call to ‘append(std::basic_ostream<char>&, const int&, const char [6], const int&)’
10:6: note: candidate is:
5:9: note: template<class Stream> Stream& append(Stream&)
5:9: note: template argument deduction/substitution failed:
10:6: note: candidate expects 1 argument, 4 provided
質問
だから私の中心的な質問はこれです:
このコードが失敗する正当な理由はありますか?
私のコードが無効であると言っている標準からの引用、またはここでの実装で何が問題になっているのかについての洞察に興味があります。誰かがこれに対するgccバグを見つけた場合、それも答えになります。適切なレポートを見つけることができませんでした。std::ostream
私の現在のアプリケーションでは十分に機能するだけですが、これを機能させる方法も素晴らしいでしょう。他のコンパイラがこれをどのように処理するかについての入力もありがたいですが、私が受け入れると思う答えには十分ではありません。