String building

Discussion in 'C++' started by woodbrian77@gmail.com, May 19, 2013.

  1. Guest

    I have this class:

    class failure : public ::std::exception {
    ::std::string whatStr;

    public:
    explicit failure :):std::string what_) : whatStr:):std::move(what_))
    {}

    ~failure () throw()
    {}

    char const* what () const throw()
    { return whatStr.c_str(); }

    template <class T>
    failure& operator<< (T val)
    {
    ::std::eek:stringstream ss;
    ss << val;
    whatStr.append(ss.str().c_str());
    return *this;
    }
    };


    If in some function I write this:

    throw failure("Getaddrinfo: ") << gai_strerror(err); // << version

    the executable/output from clang 3.2 is 96 bytes more than
    if I write it this way:

    throw failure:):std::string("Getaddrinfo: ").append(gai_strerror(err)));

    Using g++ 4.8.0 20130310, the executable for the "<< version"
    is 120 bytes larger than the version that uses string::append.

    While looking at this, one thing I tried was changing this:

    failure& operator<< (T val)

    to
    failure& operator<< (T const& val)

    but the size of one executable increased by about 9%
    (over 5,000 bytes) when I tried that.

    Do you suggest going with the append version? Any
    other options? Tia.


    Brian
    Ebenezer Enterprises - In G-d we trust.
    http://webEbenezer.net
    , May 19, 2013
    #1
    1. Advertising

  2. Guest

    On Sunday, May 19, 2013 9:01:17 PM UTC, wrote:
    > I have this class:
    >
    >
    >
    > class failure : public ::std::exception {
    >
    > ::std::string whatStr;
    >
    >
    >
    > public:
    >
    > explicit failure :):std::string what_) : whatStr:):std::move(what_))
    >
    > {}
    >
    >
    >
    > ~failure () throw()
    >
    > {}
    >
    >
    >
    > char const* what () const throw()
    >
    > { return whatStr.c_str(); }
    >
    >
    >
    > template <class T>
    >
    > failure& operator<< (T val)
    >
    > {
    >
    > ::std::eek:stringstream ss;
    >
    > ss << val;
    >
    > whatStr.append(ss.str().c_str());
    >
    > return *this;
    >
    > }
    >
    > };
    >
    >
    >
    >
    >
    > If in some function I write this:
    >
    >
    >
    > throw failure("Getaddrinfo: ") << gai_strerror(err); // << version
    >
    >
    >
    > the executable/output from clang 3.2 is 96 bytes more than
    >
    > if I write it this way:
    >
    >
    >
    > throw failure:):std::string("Getaddrinfo: ").append(gai_strerror(err)));
    >
    >
    >
    > Using g++ 4.8.0 20130310, the executable for the "<< version"
    >
    > is 120 bytes larger than the version that uses string::append.
    >


    I guess both versions use append. I mean here the
    version that uses append at the top level.
    , May 19, 2013
    #2
    1. Advertising

  3. Ian Collins Guest

    wrote:
    > I have this class:
    >
    > class failure : public ::std::exception {
    > ::std::string whatStr;
    >
    > public:
    > explicit failure :):std::string what_) : whatStr:):std::move(what_))
    > {}
    >
    > ~failure () throw()
    > {}
    >
    > char const* what () const throw()
    > { return whatStr.c_str(); }
    >
    > template <class T>
    > failure& operator<< (T val)
    > {
    > ::std::eek:stringstream ss;
    > ss << val;
    > whatStr.append(ss.str().c_str());
    > return *this;
    > }
    > };
    >
    >
    > If in some function I write this:
    >
    > throw failure("Getaddrinfo: ") << gai_strerror(err); // << version
    >
    > the executable/output from clang 3.2 is 96 bytes more than
    > if I write it this way:
    >
    > throw failure:):std::string("Getaddrinfo: ").append(gai_strerror(err)));
    >
    > Using g++ 4.8.0 20130310, the executable for the "<< version"
    > is 120 bytes larger than the version that uses string::append.
    >
    > While looking at this, one thing I tried was changing this:
    >
    > failure& operator<< (T val)
    >
    > to
    > failure& operator<< (T const& val)
    >
    > but the size of one executable increased by about 9%
    > (over 5,000 bytes) when I tried that.
    >
    > Do you suggest going with the append version? Any
    > other options? Tia.


    What append version? You don't show it.

    By the way, please don't double space your replies!

    --
    Ian Collins
    Ian Collins, May 19, 2013
    #3
  4. Guest

    On Sunday, May 19, 2013 9:51:57 PM UTC, Ian Collins wrote:
    >
    > What append version? You don't show it.
    >
    >


    throw failure("Getaddrinfo: ") << gai_strerror(err); // version 1

    throw failure:):std::string("Getaddrinfo: ").append(gai_strerror(err))); // version 2

    I mean the line that I commented as version 2. (That is
    shown in the original post.)
    , May 19, 2013
    #4
  5. Ian Collins Guest

    wrote:
    > On Sunday, May 19, 2013 9:51:57 PM UTC, Ian Collins wrote:
    >>
    >> What append version? You don't show it.
    >>
    >>

    >
    > throw failure("Getaddrinfo: ") << gai_strerror(err); // version 1
    >
    > throw failure:):std::string("Getaddrinfo: ").append(gai_strerror(err))); // version 2
    >
    > I mean the line that I commented as version 2. (That is
    > shown in the original post.)


    Your failure class doesn't have an append method.

    --
    Ian Collins
    Ian Collins, May 19, 2013
    #5
  6. Guest

    On Sunday, May 19, 2013 10:23:23 PM UTC, Ian Collins wrote:
    >
    >
    > Your failure class doesn't have an append method.
    >


    I just added this to the failure class

    failure& operator<< (char const* str)
    {
    whatStr.append(str);
    return *this;
    }

    And now the executable is building smaller. Thanks.
    , May 19, 2013
    #6
  7. On May 19, 2:01 pm, wrote:
    > Using g++ 4.8.0 20130310, the executable for the "<< version"
    > is 120 bytes larger than the version that uses string::append.


    Did you use the standard optimizer settings for the compiler and
    linker? What settings did you use?
    Joshua Maurice, May 20, 2013
    #7
  8. Ike Naar Guest

    On 2013-05-19, <> wrote:
    > template <class T>
    > failure& operator<< (T val)
    > {
    > ::std::eek:stringstream ss;
    > ss << val;
    > whatStr.append(ss.str().c_str());


    why not

    whatStr.append(ss.str());

    ?
    Ike Naar, May 20, 2013
    #8
  9. Guest

    On Sunday, May 19, 2013 11:05:53 PM UTC-5, Joshua Maurice wrote:
    >
    > Did you use the standard optimizer settings for the compiler and
    >
    > linker? What settings did you use?


    The makefile is here --
    http://webEbenezer.net/misc/makefile

    I think it has -O3 for optimization.
    , May 20, 2013
    #9
  10. Guest

    On Sunday, May 19, 2013 11:57:17 PM UTC-5, Ike Naar wrote:
    >
    > why not
    >
    >
    > whatStr.append(ss.str());
    >
    >
    > ?


    I think the reason I had it the other way was because
    it was a little smaller in terms of the size of the
    executable -- not the most profound reason, but that's
    probably what it was -- maybe 16 or 32 bytes smaller.

    I did check that again recently and remembered that
    there was a potential reason for using c_str()
    there.

    I reworked that function now to use the char const*
    version that I added:

    failure& operator<< (char const* str)
    {
    whatStr.append(str);
    return *this;
    }

    template <class T>
    failure& operator<< (T val)
    {
    ::std::eek:stringstream ss;
    ss << val;
    return operator<<(ss.str().c_str());
    }
    , May 20, 2013
    #10
  11. Ike Naar Guest

    On 2013-05-20, <> wrote:
    > On Sunday, May 19, 2013 11:57:17 PM UTC-5, Ike Naar wrote:
    >> why not
    >>
    >> whatStr.append(ss.str());
    >>
    >> ?

    >
    > I think the reason I had it the other way was because
    > it was a little smaller in terms of the size of the
    > executable -- not the most profound reason, but that's
    > probably what it was -- maybe 16 or 32 bytes smaller.
    >
    > I did check that again recently and remembered that
    > there was a potential reason for using c_str()
    > there.


    Interesting. With gcc (NetBSD nb2 20110806) 4.5.3
    it's the other way around:

    whatStr.append(ss.str());

    procuces smaller executable code than

    whatStr.append(ss.str().c_str());
    Ike Naar, May 20, 2013
    #11
  12. Ian Collins Guest

    wrote:
    > On Sunday, May 19, 2013 11:57:17 PM UTC-5, Ike Naar wrote:
    >>
    >> why not
    >>
    >>
    >> whatStr.append(ss.str());
    >>
    >>
    >> ?

    >
    > I think the reason I had it the other way was because
    > it was a little smaller in terms of the size of the
    > executable -- not the most profound reason, but that's
    > probably what it was -- maybe 16 or 32 bytes smaller.
    >
    > I did check that again recently and remembered that
    > there was a potential reason for using c_str()
    > there.
    >
    > I reworked that function now to use the char const*
    > version that I added:
    >
    > failure& operator<< (char const* str)
    > {
    > whatStr.append(str);
    > return *this;
    > }
    >
    > template <class T>
    > failure& operator<< (T val)
    > {
    > ::std::eek:stringstream ss;
    > ss << val;
    > return operator<<(ss.str().c_str());
    > }


    Rather than adding a specialisation to the class, I would add them outside:

    template <>
    failure& failure::eek:perator<<( const std::string& s )
    {
    whatStr.append(s);
    return *this;
    }

    template <>
    failure& failure::eek:perator<<( const char* s )
    {
    whatStr.append(s);
    return *this;
    }

    You can apply the same technique with any other types you want to append.

    --
    Ian Collins
    Ian Collins, May 20, 2013
    #12
  13. Guest

    On Monday, May 20, 2013 8:01:44 PM UTC, Ian Collins wrote:
    >
    > Rather than adding a specialisation to the class, I would add them outside:
    >


    What's the reason for that? I've heard of that but
    can't remember why that is suggested.
    , May 21, 2013
    #13
  14. Ian Collins Guest

    wrote:
    > On Monday, May 20, 2013 8:01:44 PM UTC, Ian Collins wrote:
    >>
    >> Rather than adding a specialisation to the class, I would add them outside:
    >>

    >
    > What's the reason for that? I've heard of that but
    > can't remember why that is suggested.


    One of the advantages of C++ is you don't have to keep updating a class
    in order to specialise template member functions. Consider the case
    where you can't change the class. It's similar in a way to adding user
    defined output operators instead of updating std::eek:stream.

    --
    Ian Collins
    Ian Collins, May 21, 2013
    #14
  15. Guest

    On Monday, May 20, 2013 8:01:44 PM UTC, Ian Collins wrote:
    >
    > Rather than adding a specialisation to the class, I would add them outside:
    >
    >
    > template <>
    > failure& failure::eek:perator<<( const std::string& s )
    > {
    > whatStr.append(s);
    > return *this;
    > }
    >


    I knew that adding an overload for std::string made sense,
    but was surprised by how the executable shrank by about
    2,000 bytes with that in there. I don't see any where
    I'm appending a std::string object to an exception message
    when I throw. I have some code like this

    throw failure("Read -- read len: ") << len << " errno: " << errno;

    and figured " errno: " would match the char const* version.
    , May 21, 2013
    #15
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jacob Arthur

    Select string building in C# and ASP.NET

    Jacob Arthur, Dec 22, 2005, in forum: ASP .Net
    Replies:
    8
    Views:
    7,294
    Steven Cheng[MSFT]
    Dec 28, 2005
  2. K.S.
    Replies:
    5
    Views:
    691
    John Harrison
    Aug 20, 2003
  3. Ian Gibbons

    Help with building a string

    Ian Gibbons, Jan 18, 2004, in forum: C Programming
    Replies:
    6
    Views:
    332
    Ian Gibbons
    Jan 18, 2004
  4. John Salerno

    string building

    John Salerno, Apr 3, 2006, in forum: Python
    Replies:
    5
    Views:
    466
    John Salerno
    Apr 3, 2006
  5. Midex
    Replies:
    24
    Views:
    885
Loading...

Share This Page