1

I have an idea how to simplify remove code repeats. Please help me to understand if it usable, good, and may be let's upgrade.

struct NetAdres
{
    /*#1*/NetAdres(const std::string &str, uint16_t port);  //#1
    /*#2*/NetAdres(std::string &&str, uint16_t port) : NetAdres(std::move(str), port) {};  //#2
    /*#3*/NetAdres(const char *str, uint16_t port) : NetAdres(std::string(str), port) {};  //#3
}

This call

NetAdres("192.168.2.3", 80);

as far as I understand calls #3->#2->#1. And this call

NetAdres(std::string("192.168.2.3"), 80);

#2->#1. Does such implementation give no extra copy of std::string?

kyb
  • 7,233
  • 5
  • 52
  • 105
  • 1
    If your base case only requires reading a string (i.e., `const std::string&`), then there's no reason to provide the other overloads. Temporary strings will bind to it just fine. – GManNickG Nov 18 '16 at 18:24
  • 4
    Why would any of those call one of the others? There's a mismatch in number of parameters. – aschepler Nov 18 '16 at 18:24
  • 3
    Your calls to #1 include AF_INET, but the signature of #1 does not allow it. – Jonas Nov 18 '16 at 18:32
  • #2 and # 3 seems to call some undefined 3 parameter ''base" class ctor? – 2785528 Nov 18 '16 at 18:43
  • And you try to bind a `const std::string` to a `std::string&&`. Then move from it. lol – Lightness Races in Orbit Nov 18 '16 at 19:01
  • **code fixed.** Please reread. `const char*` overload need explicitly 100%. I have a reason for that. The main point of this question is #2-#1 – kyb Nov 18 '16 at 19:49
  • #2 calls #2, not #1 – `NetAdres(std::string &&str, uint16_t port) : NetAdres(std::move(str), port) {}` is infinitely recursive. Attempting to run this code at all would have made that obvious. – ildjarn Nov 18 '16 at 22:05

1 Answers1

2

One possible solution is to pass by value, e.g.:

struct NetAddress
{
    std::string addr_;
    uint16_t port_;
    NetAddress(std::string addr, uint16_t port)
        : addr_(std::move(addr)) // <--- always involves one move
        , port_(port)
    {}
};

And then call it like:

NetAddress a("example.com", 443);

// or
std::string addr("example.com");
NetAddress b(addr, 443);

// or with move
NetAddress c(std::move(addr), 443); 

The downside is that it always involves one std::move, which may or may not be elided.

With g++-6.2 and pre-C++11 std::string, the last line with std::move generates the shortest assembly code.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271