相关文章推荐
腹黑的板凳  ·  basic_ifstream Class ...·  1 年前    · 
有胆有识的大蒜  ·  c++ - VS2010 compile ...·  1 年前    · 
豪爽的吐司  ·  org.quartz.impl.jdbcjo ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

How to create an boost::asio::ip::address_v6 from sockaddr_in6 without making an extra copy?

Ask Question

The problem is that address_v6 class accepts raw data strictly as bytes_type class:

typedef array< unsigned char, 16 > bytes_type;

but sockaddr_in6 struct doesn't have that, it has C-style arrays, that can't be converted to std::array without copying. So I have to create an std::array, copy data there, and pass that array to address_v6, which copies data from that std::array to its internal buffer.

I wish I could use or implement some C-style array viewer class but I wouldn't be able to pass it to the constructor anyway, because it's not a template function.

Is there some way to create an address_v6 without making an extra copy of the data?

Why are you concerned about copying just 16 bytes (two machine words on many modern systems)? – Davis Herring May 31, 2021 at 6:32 @DavisHerring due to my bad memory I forgot that array doesn't allocate its memory on heap, thus there's no overhead for that. So yeah it's fast anyway, but I was still curious how to avoid extra copying. – Nikita128 May 31, 2021 at 7:04

The std::array is required to be struct that contains raw array as its first and only non-static data member. As the raw array contains unsigned chars it is therefore standard layout class. So I can not find a reason from standard why following code would not work:

auto& bytearray = reinterpret_cast<std::array<unsigned char,16>&>(ipv6socket->sin6_addr.s6_addr); 

Replace auto& with plain auto if you want to copy.

That's exactly what I wanted! I've tried to do a similar cast, but due to my lack of experience couldn't pull it off, had mistakes here and there. But now it works, thanks! – Nikita128 May 31, 2021 at 6:58 It’s undefined behavior to use that reference for anything. Being standard-layout doesn’t mean you can pretend an object is there if it’s not. – Davis Herring May 31, 2021 at 7:22 @DavisHerring why is it UB? If I'm fully aware of the insides of the class, and I'm sure they correspond with the data I'm casting from, it's still UB? – Nikita128 May 31, 2021 at 8:45 @DavisHerring I do agree that std::array is specified very carefully to be bit-compatible with C-style arrays (imagine the riots from game devs, had they standardized otherwise). It should not be hard to find the authoritative section on this – sehe May 31, 2021 at 12:16 @Nikita128: [basic.lval]/11 provides the spirit of the rule, but actually applies only to scalars. [expr.static.cast]/13 describes the failure of the reinterpret_cast to find an appropriate object (not just type!), and then eventually [expr.ref]/6.2 or [expr.call]/2 produces undefined behavior by omission for want of an object with the given member (function). – Davis Herring May 31, 2021 at 15:39 Yeah, you've just reminded me that std::array has no memory allocations on heap, so there is no overhead for that. But still I wanted to figure out how to avoid extra copying. – Nikita128 May 31, 2021 at 7:00

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.