春鳥 -ハルドリ-

2015年1月~12月

2015-06-13(SAT)

C++でGetBytes

.NETのBitConverter.GetBytesっぽいのをC++で書いた。

まずは、使用例。

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include "./Lib/Converter/GetBytes.h"

template<std::size_t Size>
void PrintBytes(const std::array<std::uint8_t, Size>& bytes)
{
    for(std::uint8_t value : bytes)
    {
        std::cout << "0x" << std::hex << static_cast<std::uint32_t>(value) << " ";
    }

    std::cout << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    auto bytes1 = Lib::Converter::GetBytes(true);
    auto bytes2 = Lib::Converter::GetBytes('a');
    auto bytes3 = Lib::Converter::GetBytes(0x12345678);
    auto bytes4 = Lib::Converter::GetBytes(1.1f);
    auto bytes5 = Lib::Converter::GetBytes(1.1);

    PrintBytes(bytes1);
    PrintBytes(bytes2);
    PrintBytes(bytes3);
    PrintBytes(bytes4);
    PrintBytes(bytes5);

    std::cout << "[Enter]キーをッタァーン!ってすると終了します。" << std::endl;
    std::string dummy;
    std::getline(std::cin, dummy);

    return 0;
}

戻り値の型は、std::array<std::uint8_t,N>で返します。std::vectorでも良いけれど、コンパイル時に大きさが決まっているものを可変長にするのが何か嫌だというC++脳。std::arrayだと、別の関数に渡すとき、使用例のPrintBytesみたいにテンプレート関数にしないといけないのが、ちょっと不便ですな。

実装は以下。テンプレート引数サイズのstd::array<std::uint8_t,N>を用意して、memcpyするだけ。

#ifndef LIB_CONVERTER_GET_BYTES_H
#define LIB_CONVERTER_GET_BYTES_H

#include <cstdint>
#include <memory.h>
#include <array>
#include <type_traits>

namespace Lib { namespace Converter {

template<typename T> inline
std::array<std::uint8_t, sizeof(T)> GetBytes(T value,
    typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr)
{
    std::array<std::uint8_t, sizeof(T)> results = { };

    memcpy_s(results.data(), results.size(), &value, sizeof(T));

    return results;
}

} } // namespace Lib::Converter

#endif LIB_CONVERTER_GET_BYTES_H