2016-05-05 7 views
1

同様の条件であるHandling different datatypes in a single structure 私はunionを使用して実装していますが、メモリのサイズとして最も高い変数型を使用するため、64ビット8ビットの可変型の場合。また、特定のデータ型の値を取得/設定するための関数をいくつか記述していました。C++のテンプレートを使用して異なるデータ型の値を取得および設定

例:

class CDataType { 

public: 
    void setTBOOL8(bool src) { 
     m_uAnyData.um_Bool = src; 
    } 

void setTUINT8(uint8_t src) { //also used for FzrteByte 
    m_uAnyData.um_UInt8 = src; 
} 

...... 

bool getTBOOL8() const { 
    return (m_uAnyData.um_Bool); 
} 

uint8_t getTUINT8() const { //also used for FzrteByte 
    return (m_uAnyData.um_UInt8); 
} 

....... 
private: 
    union uAnyData { 
     bool  um_Bool; 
     uint8_t um_Byte; 
     uint16_t um_Word; 
     uint32_t um_DWord; 
     uint64_t um_LWord; 

    uint8_t um_UInt8; 
    uint16_t um_UInt16; 
    uint32_t um_UInt32; 
    uint64_t um_UInt64; 

    int8_t um_Int8; 
    int16_t um_Int16; 
    int32_t um_Int32; 
    int64_t um_Int64; 

    float um_Float; 
    double um_DFloat; 
}; 

uAnyData m_uAnyData; 
}; 

だから私はテンプレート

class CDataType { 
public: 
    virtual void get() = 0; 
} 

template<class T> MyDataType public CDataType{ 
private: 
    private T data_; 

public: 
    MyVariantType(T data) { 
     data_ = data; 
    } 

    virtual T get() { 
     return data_; 
    } 
} 

CDataType* var = new MyDataType<int>(100); 
var->get(); 
var = new MyDataType<string>("hello world"); 
var->get(); 
+0

あなたが実際にそれをどうするかしたいですか? – xaxxon

+0

_ "テンプレートを使用して代替ソリューションを探していたためです" _実際のタイプ(例:列挙型)の識別テンプレートパラメータによっては、特殊化が必要でした。 –

+0

checkout 'boost:variant' –

答えて

1

を使用して代替ソリューションを探していた私は、あなたが望むものについてそれほど明確でないんだけど、あなたのコメントのいずれかから、それはのように思えますこれは役に立つかもしれません。 (または少なくとも コードからいくつかのアイデアを得るかもしれません)

TPunクラスは、ポインタやオブジェクトへの参照を使用してメモリ内のある場所をポイントし、任意のオフセットから値を読み取ることができますバッファの先頭から

main()のデモンストレーションを見て、どのように使用できるかを見てください。

#include <iostream> 
#include <string> 
#include <sstream> 
#include <cstring> 
#include <cstddef> 

class TPun { 
    const void* pbuffer; 
    template <typename IT> 
    const void* offset_ptr(IT byte_offset) const { 
     return static_cast<const void*>(static_cast<const char*>(pbuffer) + byte_offset); 
    } 
public: 
    TPun() : pbuffer(nullptr) {} 

    template <typename T> 
    TPun(const T* pbuffer) : pbuffer(static_cast<const void*>(pbuffer)) {} 
    template <typename T> 
    TPun(T* pbuffer) : pbuffer(static_cast<const void*>(pbuffer)) {} 
    template <typename T> 
    TPun(const T& struct_obj) : pbuffer(static_cast<const void*>(&struct_obj)) {} 

    template <typename T> 
    TPun& operator = (const T* pbuf) { pbuffer = static_cast<const void*>(pbuf); return *this; } 
    template <typename T> 
    TPun& operator = (T* pbuf) { pbuffer = static_cast<const void*>(pbuf); return *this; } 
    template <typename T> 
    TPun& operator = (const T& struct_obj) { pbuffer = static_cast<const void*>(&struct_obj); return *this; } 

    template <typename T> 
    struct is_cchar_ptr { 
     template <typename U> static U& dval(); 
     static int test(char const * const &) { return true; } 
     template <typename U> 
     static char test(const U&) { return false; } 
     static const bool value = sizeof(int) == sizeof(test(dval<T>())); 
    }; 

    // Returns a reference for non-pointer types (only used for const char*) 
    template <typename T> struct cptr_pass   { static const T& get(const void* p) { return *static_cast<const T*>(p); } }; 
    template <typename T> struct cptr_pass<const T*> { static const T* get(const void* p) { return static_cast<const T*>(p); } }; 

    // at only works for POD types or classes consisting of only POD members 
    template <typename T, typename IT> 
    T at(IT byte_offset) const { 
     if(is_cchar_ptr<T>::value) { 
      // special handling when T is const char* 
      // returns a pointer to the buffer instead of a pointer created from buffer data 
      // using char to access the buffer avoids the strict aliasing rule 
      return cptr_pass<T>::get(offset_ptr(byte_offset)); 
     } 
     T value; 
     std::memcpy(&value, offset_ptr(byte_offset), sizeof(T)); 
     return value; 
    } 

    // This version of at() works with any type, but sports Undefined Behavior, 
    // because it violates the strict aliasing rule. 
    // This can also cause problems if the offset you give, along with the buffer's 
    // base address result in a pointer which is not aligned properly for the type. 
    template <typename T, typename IT> 
    const T& the_at_of_many_dangers(IT byte_offset) { 
     return *static_cast<const T&>(offset_ptr(byte_offset)); 
    } 

    std::ostream& manipulate(std::ostream& is) { return is; } 

    template<typename M, typename ...Ms> 
    std::ostream& manipulate(std::ostream& is, const M& manipulator, Ms ...manips) { 
     return manipulate(is << manipulator, manips...); 
    } 

    template <typename T, typename IT, typename ...Ms> 
    std::string string_at(IT byte_offset, Ms ...manips) { 
     std::stringstream ss; 
     manipulate(ss, manips...) << at<T>(byte_offset); 
     return ss.str(); 
    } 
}; 

void no_warning_strcpy(char* d, const char* s) { while(*(d++) = *(s++)) {} } 

struct test_struct { 
    char text[10]; 
    float number; 
    int some_int; 
    double a_double; 
    test_struct() { 
     no_warning_strcpy(text, "hi there"); 
     number = 52.25; 
     some_int = 1000000000; 
     a_double = 1.2e-14; 
    } 
}; 


int main() { 
    using std::cout; 
    using std::string; 
    // create a test_struct (values are filled in automatically) 
    test_struct ts; 
    // copy ts's memory image to a char buffer 
    char* memory_buffer = new char[sizeof(ts)]; 
    std::memcpy(memory_buffer, &ts, sizeof(ts)); 
    // Create a TPun object, start off pointing at the char buffer 
    TPun tpun(memory_buffer); 
    // send some field values to cout 
    // the "offsetof" macro (defined in <cstddef>) gives the 
    // byte offset of a field in a struct 
    cout << tpun.at<const char*>(offsetof(test_struct, text)) << '\n'; 
    cout << tpun.at<float>(offsetof(test_struct, number)) << '\n'; 
    // format a value into a string. Optionally, add extra ostream manipulator arguments. 
    // This makes a string with the data from some_int, and formats it as a hex string 
    string hex_string = tpun.string_at<int>(offsetof(test_struct, some_int), std::hex); 
    cout << hex_string << '\n'; 
    // I screwed this one up -- I used the text field's data to make an int 
    // Using the manipulator this way, instead of going directly through 
    // cout, keeps cout's flags intact 
    cout << tpun.string_at<int>(offsetof(test_struct, text), std::hex) << '\n'; 
    // change a_double in the original struct 
    ts.a_double = -1; 
    // tpun is pointing at the buffer copy, so it shows the original value 
    cout << tpun.at<double>(offsetof(test_struct, a_double)) << '\n'; 
    // tpun's target can be chaged on-the-fly like this, and it can be set to 
    // view an object's memory directly, without creating a pointer. 
    tpun = ts; 
    // outputs -1 
    cout << tpun.at<double>(offsetof(test_struct, a_double)) << '\n'; 
} 

このデモプリントは:

hi there 
52.25 
3b9aca00 
74206968 
1.2e-14 
-1 
+0

ありがとう、これは少し私を助けます – kar

関連する問題