概要

  • 型の違う配列を返す関数
  • 異なる型の戻り値を持つ関数をオーバーロードするには、キャスト演算子が定義されたサブクラスを戻す関数を定義する。
  • サブクラスでキャスト演算子を定義することによって、必要な型に自動的に変換される。
  • サブクラスを使って戻せるのは「値」であり、ポインタや配列を戻すことはできない。
    • サブクラス中でメモリ確保を行っても、呼び出し元の変数にポインタをコピーした後はサブクラスのインスタンスはデストラクトされるため、ポインタの指す値は不定となってしまう。
    • サブクラス中でメモリ確保を行えないため、値の加工を行うことはできない。
      • サブクラスで保持しているポインタは元データを指しているため、加工を行うと、その後の呼び出しで破壊されたデータを読み出すことになってしまう。

ソース

  • &ref(): File not found: "OverloadedArrayReturner.zip" at page "VisualC++/OverloadedArrayReturner";

OverloadedArrayReturner.h

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
-
|
!
|
!
 
 
 
 
-
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
!
|
|
|
|
!
|
|
|
|
|
-
|
|
|
|
-
|
!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
-
|
!
!
|
|
|
|
|
-
|
|
|
|
-
|
!
|
|
!
|
|
|
|
!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
!
|
!
|
|
|
|
!
/**
	@file OverloadedArrayReturner.h
*/
 
#pragma once
 
#include <Windows.h>
#include <memory.h>
#include "DebugLog.h"
 
/**
	Big Endian ←→ Little Endian 変換
	@return	出力値
*/
template<typename T>
T swapEndian(
    const T &val    ///< 入力値
){
    T result = val;
    int len = sizeof(T);
    char *dst = (char *)&result;
    char *src = (char *)&val + len - 1;
    for( int i=0; i<len; ++i ){
        *dst++ = *src--;
    }
    return result;
}
 
/**
	戻り値の型が違う関数をオーバーロードするクラス
*/
class OverloadedArrayReturner {
public:
    
    /**
		要求される型に合うようにキャストを適用するためのサブクラス<br>
		(swap適用なし, メモリ確保なし)
	*/
    class TypeConverter1 {
    public:
        /**
			デフォルトコンストラクタ
		*/
        TypeConverter1(void) : _ptr(), _length() {}
        
        /**
			変換元データを指定するコンストラクタ
		*/
        TypeConverter1(
            char *ptr,        ///< [in] 変換元データを指すポインタ
            size_t length    ///< [in] 変換元データのバイト数
        ): _ptr(ptr), _length(length) {}
 
        /**
			キャスト演算子オーバーロード
		*/
        template<typename T>
        operator T*(){
            return (T*)_ptr;
        }
 
    private:
        char    *_ptr;        ///< 変換元データを指すポインタ
        size_t    _length;    ///< 変換元データのバイト数
    };
 
    /**
		要求される型に合うようにキャストを適用するためのサブクラス<br>
		(swap適用あり, メモリ確保あり)
	*/
    class TypeConverter2 {
    public:
        /**
			デストラクタ
		*/
        virtual ~TypeConverter2(void){
            delete[] _ptr;    _ptr = NULL;
        }
 
        /**
			デフォルトコンストラクタ
		*/
        TypeConverter2(void) : _ptr(), _length() {}
        
        /**
			変換元データを指定するコンストラクタ
		*/
        TypeConverter2(
            char *ptr,        ///< [in] 変換元データを指すポインタ
            size_t length    ///< [in] 変換元データのバイト数
        ):
            _ptr(new char[length]),
            _length(length)
        {
            if ( _ptr != NULL && _length > 0 ){
                memcpy_s(_ptr, _length, ptr, length);
            }
        }
 
        /**
			キャスト演算子オーバーロード
		*/
        template<typename T>
        operator T*(){
            DEBUG_FUNC_NAME(DebugLevel_Infomation);
            T *dst = (T*)_ptr;
            size_t typeSize = sizeof(T);
            size_t index = 0;
            for( ; index<_length/typeSize; ++index, ++dst ){
                *dst = swapEndian(*dst);
            }
            DEBUG_DUMP(DebugLevel_Infomation, _ptr, _length);
            return (T*)_ptr;
        }
 
    private:
        char    *_ptr;        ///< 変換元データを指すポインタ
        size_t    _length;    ///< 変換元データのバイト数
    };
 
    /**
		デストラクタ
	*/
    virtual ~OverloadedArrayReturner(void);
    
    /**
		デフォルトコンストラクタ
	*/
    OverloadedArrayReturner(void);
    
    /**
		データサイズを指定するコンストラクタ<br>
		変換元となるデータを用意する。
	*/
    OverloadedArrayReturner(
        size_t length            ///< [in] データのバイト数
    );
    
    /**
		オーバーロードされた戻り値を返すメソッド
		@return	キャスト演算子オーバーロードが定義されたサブクラス
	*/
    TypeConverter1 get1(void);
 
    /**
		オーバーロードされた戻り値を返すメソッド
		@return	キャスト演算子オーバーロードが定義されたサブクラス
	*/
    TypeConverter2 get2(void);
 
    /**
		オーバーロードされた配列に値を返すメソッド
		@return 配列の個数
	*/
    template<typename T>
    size_t storeToArray(
        T *target                ///< [out] データ格納先
    ){
        T *src = (T*)_ptr;
        size_t typeSize = sizeof(T);
        size_t index = 0;
        for( ; index<_length/typeSize; ++index ){
            *target++ = swapEndian(*src++);
        }
        return index;
    }
 
private:
    char    *_ptr;        ///< 変換元データを指すポインタ
    size_t    _length;    ///< 変換元データのバイト数
};

OverloadedArrayReturner.cpp

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 
 
 
 
 
-
|
!
 
 
 
 
-
!
 
 
 
 
 
 
-
|
-
|
|
-
|
!
!
|
!
 
-
|
!
 
-
|
!
#include "StdAfx.h"
#include <memory.h>
#include "OverloadedArrayReturner.h"
#include "DebugLog.h"
 
OverloadedArrayReturner::~OverloadedArrayReturner(void)
{
    delete[] _ptr;    _ptr = NULL;
}
 
OverloadedArrayReturner::OverloadedArrayReturner(void):
    _ptr(),
    _length()
{
}
 
OverloadedArrayReturner::OverloadedArrayReturner(
    size_t length
):
    _ptr(new char[length]),
    _length(length)
{
    DEBUG_FUNC_NAME(DebugLevel_Infomation);
    if ( _ptr != NULL && _length > 0 ){
        char *pos = _ptr;
        char val = 0;
        for( size_t i=0; i<_length; ++i ){
            *pos++ = val++;
        }
    }
    DEBUG_DUMP(DebugLevel_Infomation, _ptr, _length);
}
 
OverloadedArrayReturner::TypeConverter1 OverloadedArrayReturner::get1(void){
    return TypeConverter1(_ptr, _length);
}
 
OverloadedArrayReturner::TypeConverter2 OverloadedArrayReturner::get2(void){
    return TypeConverter2(_ptr, _length);
}

Main.cpp

すべてを展開すべてを収束
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
|
|
|
|
|
|
-
|
|
|
|
|
|
|
|
|
|
|
|
!
-
|
!
|
!
 
 
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
!
// Main.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//
 
#include "stdafx.h"
#include <stdio.h>
#include <locale.h>
#include "OverloadedArrayReturner.h"
#include "DebugLog.h"
 
/**
	配列を指定個数ダンプする。
*/
template<typename T>
void dump(
    T *ptr,            ///< [in] 配列の先頭を指すポインタ
    size_t count    ///< [in] 配列の個数
){
    size_t typeSize = sizeof(T);
    TCHAR fmt[16] = {0};
    _tcscpy_s( fmt, _countof(fmt), typeSize < 8
        ? _T("%%0%dx ")
        : _T("%%0%dllx ")
    );
    _stprintf_s(fmt, fmt, typeSize * 2);
    long long mask;
    switch(typeSize){
        case 1:        // char
            mask = 0x0ff;
            break;
        case 2:        // short
            mask = 0x0ffff;
            break;
        case 4:        // long
            mask = 0x0ffffffff;
            break;
        case 8:        // long long
            mask = 0x0ffffffffffffffff;
            break;
    }
    for( size_t i=0; i<count; ++i ){
        _tprintf_s(fmt, (*ptr++) & mask);
    }
    _tprintf_s( _T("\n") );
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    wchar_t wszLocale[MAX_PATH];
    GetLocaleInfoW(GetThreadLocale(), LOCALE_SABBREVLANGNAME, wszLocale, _countof(wszLocale));
    _wsetlocale(LC_ALL, wszLocale);
 
    const int length = 24;
    OverloadedArrayReturner oar( length );
 
    char *cp1 = oar.get1();
    dump(cp1, length / sizeof(char));
 
    short *sp1 = oar.get1();
    dump(sp1, length / sizeof(short));
 
    long *lp1 = oar.get1();
    dump(lp1, length / sizeof(long));
 
    long long *llp1 = oar.get1();
    dump(llp1, length / sizeof(long long));
 
    _tprintf_s( _T("\n") );
 
    char *cp2 = oar.get2();
    DEBUG_TRACE(DebugLevel_Infomation, _T("cp2\n"));
    DEBUG_DUMP(DebugLevel_Infomation, cp2, length);
    dump(cp2, length / sizeof(char));
 
    short *sp2 = oar.get2();
    DEBUG_TRACE(DebugLevel_Infomation, _T("sp2\n"));
    DEBUG_DUMP(DebugLevel_Infomation, (char*)sp2, length);
    dump(sp2, length / sizeof(short));
 
    long *lp2 = oar.get2();
    DEBUG_TRACE(DebugLevel_Infomation, _T("lp2\n"));
    DEBUG_DUMP(DebugLevel_Infomation, (char*)lp2, length);
    dump(lp2, length / sizeof(long));
 
    long long *llp2 = oar.get2();
    DEBUG_TRACE(DebugLevel_Infomation, _T("llp2\n"));
    DEBUG_DUMP(DebugLevel_Infomation, (char*)llp2, length);
    dump(llp2, length / sizeof(long long));
 
    _tprintf_s( _T("\n") );
 
    char ca[length / sizeof(char)];
    oar.storeToArray(ca);
    dump(ca, _countof(ca));
 
    short sa[length / sizeof(short)];
    oar.storeToArray(sa);
    dump(sa, _countof(sa));
 
    long la[length / sizeof(long)];
    oar.storeToArray(la);
    dump(la, _countof(la));
 
    long long lla[length / sizeof(long long)];
    oar.storeToArray(lla);
    dump(lla, _countof(lla));
 
    return 0;
}

出力

00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
0100 0302 0504 0706 0908 0b0a 0d0c 0f0e 1110 1312 1514 1716
03020100 07060504 0b0a0908 0f0e0d0c 13121110 17161514
0706050403020100 0f0e0d0c0b0a0908 1716151413121110

dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd
dddd dddd dddd dddd dddd dddd dddd dddd dddd dddd dddd dddd
dddddddd dddddddd dddddddd dddddddd dddddddd dddddddd
dddddddddddddddd dddddddddddddddd dddddddddddddddd

00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17
0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 1011 1213 1415 1617
00010203 04050607 08090a0b 0c0d0e0f 10111213 14151617
0001020304050607 08090a0b0c0d0e0f 1011121314151617

リロード   新規 下位ページ作成 編集 凍結 差分 添付 コピー 名前変更   ホーム 一覧 検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: Mon, 03 Feb 2014 20:45:09 JST (1446d)