2017-09-30 3 views
1

Hallo Ich versuche, ein Objekt des Typs T zu erstellen, wobei T ein Zeiger ist über die Verwendung von T Ergebnis = T(). Aber anstatt den Konstruktor aufzurufen, gibt es einfach einen Nullzeiger zurück. HierWie Vorlageobjekt des Typs T ordnungsgemäß zu erstellen ist, d. H. T result = T();

ist ein Beispiel für einige betroffene Code:

template <class T> 
    T readBlockchain(std::ifstream* stream) { 
     T result = T(); // Result is null after this 
     decltype(result->getLastBlock()) blkPtr = result->getLastBlock(); 
     auto blk = *blkPtr; 
     decltype(result->getLastBlock()) lastBlock = &readBlock<decltype(blk)>(stream); 
     if(!lastBlock->verify()) 
      return nullptr; 
     unsigned long count = *readUnsignedLong(stream); 
     unsigned long orphanCount = *readUnsignedLong(stream); 
     std::map<std::string, decltype(blk)> blocks = std::map<std::string, decltype(blk)>(); 
     for(int i = 0; i < count - 1; i++){ 
      decltype(blk) block = readBlock<decltype(blk)>(stream); 
      if(!block.verify()) 
       return nullptr; 
      blocks.insert(std::make_pair(block.getHash(), block)); 
     } 
     std::vector<Blockchain<decltype(blk)>*> orphanedChains = std::vector<Blockchain<decltype(blk)>*>(); 
     for(int i = 0; i < orphanCount - 1; i++){ 
      Blockchain<decltype(blk)>* orphan = &readOrphanedChain<Blockchain<decltype(blk)>>(stream); 
      orphanedChains.push_back(orphan); 
     } 
     result->setLastBlock(lastBlock); 
     result->setCount(count); 
     result->setOrphanCount(orphanCount); 
     result->setBlocks(blocks); 
     result->setOrphanedChains(orphanedChains); 
     return result; 
    } 
+2

Was ist 'T'? Wenn "T" ein Zeiger auf etwas ist, erzeugt "T()' default - einen Zeiger, der zu einem "nullptr" führt. Verwenden Sie so etwas wie 'using S = std :: decay_t ; T Ergebnis = neues S; '. – JohnB

+0

Ja T ist ein Zeiger, ich werde die Frage editieren –

+3

Warum templatisieren Sie Ihre Methode nicht auf den Typ, auf den der Zeiger zeigt, und geben ein 'T *' zurück? Das wäre transparenter. 'Vorlage T * readBlockchain (...) {T * Ergebnis = neu T; ...} '. Oder, noch besser, erstelle und gebe ein 'std :: unique_ptr ' zurück. – JohnB

Antwort

1

Wenn mein Verständnis korrekt ist. Um Ihre readBlockchain richtig zu verallgemeinern, möchten Sie, wenn T ist ein Zeiger zum Erstellen eines neuen Objekts T im Heap und wenn T ist ein konkreter Typ zum Erstellen einer regulären T Objekt durch den Konstruktor von T aufrufen. Eine Lösung wäre, das folgende Spezialisierungskonstrukt zu verwenden.

template<typename T> 
struct CreateNew { 
    template<typename... Args> 
    static T apply(Args&&... args) { return T(std::forward<Args>(args)...); } 
}; 

template<typename T> 
struct CreateNew<T*> { 
    template<typename... Args> 
    static decltype(auto) apply(Args&&... args) { return std::make_unique<T>(std::forward<Args>(args)...); } 
}; 

Das heißt, könnten Sie eine Template-Klasse erstellen, die T zusammen mit einer Spezialisierung dieser Template-Klasse für Zeiger vom Typ T* eine Vorlage Argument. Innerhalb der primären Vorlage (z. B. statische Elementfunktion apply) erstellen Sie Objekte des Typs T durch Aufrufen des Konstruktors der Klasse T und innerhalb der Spezialisierung erstellen Sie Heap-Objekte T* (Beachten Sie, dass ich in der Spezialisierung eine std::unique_ptr<T*> für Bequemlichkeit).

So Ihre readBlockChain Template-Funktion würde:

template <class T> 
decltype(auto) readBlockchain(std::ifstream* stream) { 
    auto result = CreateNew<T>::apply(/* T constructor arguments */); 
    ... 
    return result; 
} 

Live Demo

+0

Danke, krank versuchen Sie es später und lassen Sie es wissen! –

+0

Danke, das hat so funktioniert, wie ich wollte! –

Verwandte Themen