2016-04-14 11 views
-1

Ich entwickle eine Containervorlagenklasse. Dieser Code muss mit dem vorhandenen C-Code eine Schnittstelle bilden und muss binärkompatibel bleiben, so dass ich z. B. std::vector oder ähnliches nicht verwenden kann.Wählen Sie eine Methode als (Standard) Vorlagenparameter

Das Problem, das ich habe, ist, dass es unterschiedliche Allokationsstrategien unterstützen muß, und ich weiß nicht, wie der allocator als Vorlage Argument zu liefern. Ich habe eine SSCCE erstellt, um zu veranschaulichen, wie weit ich gekommen bin (was natürlich nicht kompiliert, denn wenn es so wäre, müsste ich diese Frage nicht stellen :)).

#include <iostream> 
#include <cstring> 
#include <type_traits> 

typedef unsigned int  uint_t; 
typedef signed int   int_t; 

template <typename T, typename S, typename _allocator = _virtual> 
class Container 
{ 
public: 
    Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL) 
    { 
     mItems = nItems; 
     mMaxItems = nMaxItems; 
     mArray = pArray; 
    } 

    void adjustMalloc(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T)); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjustAligned(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjustVirtual(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = VirtualAlloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjust(uint_t nClusterSize) 
    { 
     if (std::is_same<_allocator>::value == _virtual) 
      adjustVirtual(nClusterSize); 
     else if(std::is_same<_allocator>::value == _aligned) 
      adjustAligned(nClusterSize); 
     else if(std::is_same<_allocator>::value == _malloc) 
      adjustMalloc(nClusterSize); 
     else 
     { 
      // Cause a static compiler error, how? 
     } 
    } 

    bool add(T *pItem) 
    { 
     if(find(pItem) == NULL) 
     { 
      adjust(100); 
      mItems++; 

      return true; // added 
     } 

     return false; 
    } 

    T *find(T *pItem) 
    { 
     T *p = mArray; 

     for(S i = 0; i < mItems; i++, p++) 
     { 
      if(*p == *pItem) 
       return p; 
     } 

     return NULL; 
    } 

private: 
    S mItems; 
    S mMaxItems; 
    T *mArray; 
}; 


class Record 
{ 
public: 

    bool operator==(const Record &oRecord) 
    { 
     if(Id != oRecord.Id) 
      return false; 

     if(strcmp(Name, oRecord.Name) != 0) 
      return false; 

     return true; 
    } 

    int Id; 
    char Name[10+1]; 
}; 

int main(int argc, char *argv[]) 
{ 
    Record rec; 
    rec.Id = 0; 
    strcpy(rec.Name, "Test"); 

    Container<Record, uint_t> records; // Default using malloc 
    records.add(&rec); 

    if(records.find(&rec) == NULL) 
     std::cerr << "Not found" << std::endl; 

    Container<Record, uint_t, _virtual> vrecords; // VirtualAlloc allocator used. 
    vrecords.add(&rec); 

    if(records.find(&rec) == NULL) 
     std::cerr << "Not found" << std::endl; 

    return 0; 
} 

Ich verwende Visual Studio 2010, also ist es nicht 100% C++ 11.

Die VirtualAlloc ist ebenso (andere) Beispiel und wird nicht funktionieren, wie es hier dargestellt ist.

+0

Wie löst die Neuimplementierung von 'vector' Ihr Schnittstellenproblem? – Barry

+0

Ist das relevant für eine Antwort? – Devolus

+0

Ja. Gerade jetzt hat dein 'Container' einige Probleme, also würde ich gerne verstehen, was dieser Ansatz dir wirklich bringt, dass' vector' einfach nicht verwendet wird (oder 'std :: set'), basierend auf dem, was' add' tut) – Barry

Antwort

-1

Ich habe eine Lösung für mein Problem gefunden. Allerdings bekomme ich Warnungen

warning C4127: conditional expression is constant

im adjust() Verfahren zum if(std::is_same... und ich frage mich, ob das normal ist oder ob ich es bekommen kann los zu werden, anders als es zu deaktivieren.

#include "stdafx.h" 
#include "windows.h" 

#include <iostream> 
#include <cstring> 
#include <type_traits> 

#pragma warning (push) 
//#pragma warning (disable : 4127) 

typedef unsigned int  uint_t; 
typedef signed int   int_t; 

typedef struct { const static bool _virtual_allocator = true; } _virtual_type; 
typedef struct { const static bool _aligned_allocator = true; } _aligned_type; 
typedef struct { const static bool _malloc_allocator = true; } _malloc_type; 

template <typename T, typename S, typename _allocator = _aligned_type> 
class Container 
{ 
public: 
    Container(S nItems = 0, S nMaxItems = 0, T *pArray = NULL) 
    { 
     mItems = nItems; 
     mMaxItems = nMaxItems; 
     mArray = pArray; 
    } 

    void adjustMalloc(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = (T *)realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T)); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjustAligned(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = (T *)_aligned_realloc(mArray, (mMaxItems+nClusterSize)*sizeof(T), 16); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjustVirtual(uint_t nClusterSize) 
    { 
     if(mItems == mMaxItems) 
     { 
      mArray = (T *)VirtualAlloc((LPVOID)mArray, (mMaxItems+nClusterSize)*sizeof(T), MEM_RESERVE, PAGE_NOACCESS); 
      mMaxItems += nClusterSize; 
     } 
    } 

    void adjust(uint_t nClusterSize) 
    { 
     if (std::is_same<_allocator, _virtual_type>::value) 
      adjustVirtual(nClusterSize); 
     else if(std::is_same<_allocator, _aligned_type>::value) 
      adjustAligned(nClusterSize); 
     else if(std::is_same<_allocator, _malloc_type>::value) 
      adjustMalloc(nClusterSize); 
     else 
     { 
      // Cause a static compiler error, how? 
     } 
    } 

    bool add(T *pItem) 
    { 
     if(find(pItem) == NULL) 
     { 
      adjust(100); 
      mItems++; 

      return true; // added 
     } 

     return false; 
    } 

    T *find(T *pItem) 
    { 
     T *p = mArray; 

     for(S i = 0; i < mItems; i++, p++) 
     { 
      if(*p == *pItem) 
       return p; 
     } 

     return NULL; 
    } 

private: 
    S mItems; 
    S mMaxItems; 
    T *mArray; 
}; 

#pragma warning (pop) 

class Record 
{ 
public: 
    bool operator==(const Record &oRecord) 
    { 
     if(Id != oRecord.Id) 
      return false; 

     if(strcmp(Name, oRecord.Name) != 0) 
      return false; 

     return true; 
    } 

    int Id; 
    char Name[10+1]; 
}; 

int main(int argc, char *argv[]) 
{ 
    Record rec; 
    rec.Id = 0; 
    strcpy(rec.Name, "Test"); 

    Container<Record, uint_t> mrecords; 
    mrecords.add(&rec); 

    if(mrecords.find(&rec) == NULL) 
     std::cerr << "Malloc Not found" << std::endl; 

    Container<Record, uint_t, _aligned_type> arecords; 
    arecords.add(&rec); 

    if(arecords.find(&rec) == NULL) 
     std::cerr << "Aligned Not found" << std::endl; 

    Container<Record, uint_t, _virtual_type> vrecords; 
    vrecords.add(&rec); 

    if(vrecords.find(&rec) == NULL) 
     std::cerr << "Virtual Not found" << std::endl; 

    return 0; 
} 
+0

Warum der Downvote? – Devolus

Verwandte Themen