2

I'm learning socket programming and need to convert data from host byte order(in my case LITTLE ENDIAN) to network byte order. So I need to swap the byte order of the data that I will be sending. So, I used to std::memcpy say integer into a temp char array, then swap the bytes of that temp char array. But now I'm trying to achieve the same using std::reverse_copy but not been able to achieve(not compiling itself). This is my sample code:

#include <iostream>
#include <cstring>
#include <algorithm>

int main()
{
    const int a = 0x89ABCDEF;
    char arr[sizeof(decltype(a))] {};
    char r_arr[sizeof(decltype(a))] {};
    
    std::memcpy(arr, reinterpret_cast<const char*>(&a), sizeof(decltype(a)));
    char *start = arr;
    char *end = arr + sizeof(decltype(a)) - 1;
    while (start < end) {
        char temp = *start;
        *start = *end;
        *end = temp;
        
        ++start;
        --end;
    }
    for (int32_t i = 0; i < sizeof(decltype(a)); ++i)
        std::cout << std::hex << static_cast<uint16_t>(arr[i]) << std::endl;
    
    // error in below line
    // std::reverse_copy(std::begin(reinterpret_cast<const char*>(&a)), std::begin(reinterpret_cast<const char*>(&a)) + sizeof(decltype(a)), std::begin(r_arr));
    for (int32_t i = 0; i < sizeof(decltype(a)); ++i)
        std::cout << std::hex << static_cast<uint16_t>(r_arr[i]) << std::endl;
        
    return 0;
}
1
  • please post the code that actually has the error (ie no // in front of std::reverse_copy..) and the error message Commented Jan 18, 2021 at 16:13

2 Answers 2

4

You have too many calls to std::begin. You want just:

std::reverse_copy(reinterpret_cast<const char*>(&a), reinterpret_cast<const char*>(&a) + sizeof(decltype(a)), r_arr);
Sign up to request clarification or add additional context in comments.

Comments

1

This calls for a type-casting view that can be used both in C++20 ranges-based code and in iterators-based pre-C++20 code. That way you don't need to mess with temporary char buffers etc.

#include <algorithm>

template <typename Src>
class const_char_view_t {
    const Src &src;
public:
    explicit const_char_view_t(const Src &src) : src(src) {}
    const char * begin() const noexcept {
        return reinterpret_cast<const char*>(&src);
    }
    const char * end() const noexcept { 
        return reinterpret_cast<const char*>((&src)+1);
    }
};

template <typename Src>
auto const_char_view(const Src &val) {
    return const_char_view_t<Src>(val);
}

template <typename Out>
class tie_out_adapter_t {
    Out &out;
public:
    explicit tie_out_adapter_t(Out &out) : out(out) {}
    template <typename Src>
    Out &operator=(Src &&src) {
        return (out = std::move(src.out));
    }
};
template <typename Out>
auto tie_out(Out && out) { return tie_out_adapter_t(out); }

The usage example below demonstrates the use of the above, as well as how to use the iterators returned by std::[ranges::]reverse_copy to concatenate successive elements into an output vector.

To use ranges, -std=c++20 (at least) compiler option has to be provided to gcc, clang and MSVC.

#include <cassert>
#include <iterator>
#include <vector>
#ifdef __has_include
#   if __has_include(<version>)
#   include <version>
#       if __cpp_lib_ranges >= 201911L
#       define HAS_RANGES 1
#       endif
#   endif
#endif

int main() {
    int32_t val_1 = 0x01234567;
    int16_t val_2 = 0x89AB;
    const char copy_expected[4+2] = {'\x01','\x23','\x45','\x67','\x89','\xAB'};

    #if HAS_RANGES
    {
        std::vector<char> copy;
        auto out = std::back_inserter(copy);
        tie_out(out) = std::ranges::reverse_copy(const_char_view(val_1), out);
        tie_out(out) = std::ranges::reverse_copy(const_char_view(val_2), out);
        assert(std::ranges::equal(copy, copy_expected));
        copy.clear();
    }
    #endif

    std::vector<char> copy;
    auto out = std::back_inserter(copy);
    out = std::reverse_copy(cchar_begin(val_1), cchar_end(val_1), out);
    out = std::reverse_copy(cchar_begin(val_2), cchar_end(val_2), out);
    assert(std::equal(std::begin(copy), std::end(copy), std::begin(copy_expected)));
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.