Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8269157
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 8, 20262026-06-08T06:07:47+00:00 2026-06-08T06:07:47+00:00

This works Toying with C++11, I tried to build a function which concatenates arbitrary

  • 0

This works

Toying with C++11, I tried to build a function which concatenates arbitrary objects by writing them to a ostringstream. As a helper function for those, I have a variadic helper function which appends a single item to an existing ostream (More context given in the full paste below):

template<class Head, class... Tail>
std::ostream& append(std::ostream& out, const Head& head, const Tail&... tail)
{
  return append(out << head, tail...);
}

This fails

But then I thought that there might be some objects which, when <<-applied to a stream, will not return an ostream but instead some placeholder. So it would be cool to have the stream type a template argument as well:

  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 }

But g++-4.7.1 will refuse to compile this.

Changing all uses of Stream in the signature back to std::ostream will not make it any better, so I assume that the new function declaration syntax is playing a major role here ­– even though gcc claims to support it since 4.4.

Error message

The error message is rather cryptic, and doesn’t tell me what’s going on here. But perhaps you can make any sense of it.

 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

Question

So my core question is this:
Is there a good reason for this code to fail?

I’d be interested either in some quote from the standard which says my code is invalid, or some insight as to what’s going wrong here in the implementation. If anyone should find a gcc bug for this, that would be an answer, too. I haven’t been able to find a suitable report. A way to make this work would be great, too, although using std::ostream only works well enough for my current application. Input about how other compilers handle this is appreciated as well, but won’t be enough for an answer I’d consider to accept.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-08T06:07:48+00:00Added an answer on June 8, 2026 at 6:07 am

    3.3.2 [basic.scope.pdecl]
    -1- The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.

    A function declarator includes the trailing return type, so a function’s own name is not in scope in its own trailing return type.

    So in the expression decltype(append(out << head, tail...)) the only candidate function is the non-variadic append(Stream&) which cannot be used when the parameter pack tail is not empty, so deduction always fails when calling append with more than two arguments.

    Therefore GCC is correct to reject the code.

    This was discussed by the standard committee members last December and reported as a core issue, see CWG 1433.

    The only workaround I can think of right now is to try using common_type, which will work for some cases, but probably fail for others:

    template<class Stream, class Head, class... Tail>
      auto append(Stream& out, const Head& head, const Tail&... tail)
      -> typename std::common_type<decltype(out << head), decltype(out << tail)...>::type
    

    This would fail if out << head << tail is valid but out << tail is not, or if any of the operator<< calls returns something that cannot be converted to the type returned by the other operator<< calls.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to figure out why this works: >>> comments = Comment.objects.all() >>>[c.content_object for
This works when I used a rectangle as the food but now I'm trying
I'm trying to figure out why this works in FireFox, Chrome but not in
I'm trying to parse 3 arguments (this works) and request a file that has
I'm trying to initialize string with iterators and something like this works: ifstream fin(tmp.txt);
I'm trying to follow these docs: http://readthedocs.org/docs/neo4j-rest-client/en/latest/indices.html This works fine from neo4jrestclient.client import GraphDatabase,
I am trying to use Desktop .browse() to invoke a URL, this works fine
I am trying to print a portion of the page in FF3. This works
I am trying to send user to previous page history.go(-1). This works fine in
I'm trying to seed my database with the standard db/seeds.rb method. This works fine

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.