Tidak dapat mengonversi dari std::shared_ptr‹_Ty› ke std::shared_ptr‹_Ty›

Saya mendapatkan kesalahan berikut:

kesalahan C2440: 'static_cast' : tidak dapat mengonversi dari 'std::shared_ptr‹_Ty>' ke 'std::shared_ptr‹_Ty> stack\genericstack.h 36 1 Tumpukan

GenericStack.h

#ifndef _GENERIC_STACK_TROFIMOV_H_
#define _GENERIC_STACK_TROFIMOV_H_

#include <memory>

class GenericStack {
    struct StackNode {
        std::shared_ptr<void> _data; 
        StackNode* _next;
        StackNode(const std::shared_ptr<void>& data, StackNode* next) 
            : _data(data), _next(next) {

        }
    };

    StackNode* _top; 

    GenericStack(const GenericStack&);
    GenericStack& operator=(const GenericStack&);

protected:
    GenericStack();
    ~GenericStack();
    void push(const std::shared_ptr<void>&);
    void pop();
    std::shared_ptr<void>& top();
    bool isEmpty() const;
};

template <class T>
class TStack: private GenericStack {                  
public:
    void push(const std::shared_ptr<T>& p) { GenericStack::push(p); }
    void pop() { GenericStack::pop(); }
    std::shared_ptr<T> top() { return static_cast<std::shared_ptr<T>>(GenericStack::top()); }
    bool empty() const { return GenericStack::isEmpty(); }
};

#endif

GenerickStack.cpp

#include "GenericStack.h"

GenericStack::GenericStack()
    :_top(0) {

};
GenericStack::~GenericStack() {
    while(!isEmpty()) {
        pop();
    }
};

void GenericStack::push(const std::shared_ptr<void>& element) {
    _top = new StackNode(element, _top);
}

std::shared_ptr<void>& GenericStack::top() {
    return _top->_data;
}
void GenericStack::pop() {
    StackNode* t = _top->_next;
    delete _top;
    _top = t;
}

bool GenericStack::isEmpty() const {
    return !_top;
}

Utama.cpp

#include <iostream>
#include "GenericStack.h"

int main() {
    TStack<int> gs;

    std::shared_ptr<int> sh(new int(7));
    gs.push(sh);
    std::cout << *gs.top() << std::endl;

    return 0;
}

Mengapa saya mendapatkan kesalahan?

Saya berharap pemeran akan berhasil, karena dengan pointer mentah saya selalu dapat mengubah huruf dari void* ke pointer tipe sebenarnya.

Yang ingin saya lakukan di sini adalah membuat templat tumpukan. Namun saya mencoba menggunakan kembali kode sebanyak yang saya bisa, sehingga kelas yang ditemplat tidak terlalu membengkak.

Terima kasih.


person yourbuddy    schedule 25.11.2018    source sumber
comment
Saya berharap pemeran akan berhasil, karena dengan pointer mentah saya selalu dapat meng-case dari void* ke pointer tipe sebenarnya. Karena std::shared_ptr menjaga keamanan tipe, dan Anda mencoba membuangnya. Ingat juga bahwa berhasil hanya akan melindungi Anda dari kesalahan kompiler yang mencolok, dan tidak aman terkait dengan perilaku tidak terdefinisi.   -  person πάντα ῥεῖ    schedule 25.11.2018
comment
@ πάνταῥεῖ, apakah yang saya coba lakukan tidak mungkin?   -  person yourbuddy    schedule 25.11.2018
comment
apakah yang saya coba lakukan tidak mungkin? Tergantung pada bagaimana tipe-tipe ini berhubungan satu sama lain.   -  person πάντα ῥεῖ    schedule 25.11.2018
comment
Nitpick (tidak terkait dengan pertanyaan Anda, tetapi penting secara teknis): penggunaan pengidentifikasi _GENERIC_STACK_TROFIMOV_H_. Ini secara formal merupakan pengenal khusus.   -  person curiousguy    schedule 25.11.2018
comment
@πάνταῥεῖ, tidak ada hubungannya, tetapi setiap kali pemeran dilakukan dijamin sebelumnya telah menggantikan shared_ptr<void> shared_ptr<T>.   -  person yourbuddy    schedule 25.11.2018
comment
@curiousguy, menurut saya pengenalnya tidak akan digunakan di mana pun, tapi terima kasih, saya memahami masalah yang Anda tunjukkan.   -  person yourbuddy    schedule 25.11.2018
comment
static_cast 1) bukan operator yang dapat kelebihan beban 2) untuk tipe yang ditentukan pengguna: hanya dapat melakukan apa yang dapat dilakukan oleh panggilan konstruktor   -  person curiousguy    schedule 25.11.2018


Jawaban (2)


Anda mendapatkan kesalahan itu karena static_cast memerlukan tipe from dan to agar dapat dikonversi. Untuk shared_ptr itu hanya akan berlaku jika c'tor kelebihan beban 9 akan berpartisipasi dalam resolusi kelebihan beban. Namun ternyata tidak, karena void* tidak secara implisit dapat dikonversi ke tipe penunjuk objek lain di C++, ia memerlukan static_cast secara eksplisit.

Jika Anda ingin mengonversi pointer bersama berdasarkan static_casting jenis pointer terkelola, Anda perlu menggunakan std::static_pointer_cast, itulah gunanya.

Jadi setelah memasang perbaikan itu

 std::shared_ptr<T> top() { return std::static_pointer_cast<T>(GenericStack::top()); }

Pembungkus templat tipis Anda akan dibuat dengan baik.

person StoryTeller - Unslander Monica    schedule 25.11.2018
comment
Bisakah Anda membantu saya mengatasi masalah lain di chat? - person yourbuddy; 25.11.2018
comment
@yourbuddy - Jika Anda memiliki masalah lain, mungkin ada baiknya mengajukan pertanyaan lain. - person StoryTeller - Unslander Monica; 25.11.2018
comment
Ini. Terima kasih. - person yourbuddy; 25.11.2018

Lihat daftar konstruktor untuk shared_ptr. Anda mencoba menggunakan kelebihan 9, lebih khusus lagi kelebihan template dengan Y = void dan T = int. Namun, kelebihan template ini tidak ikut serta dalam penyelesaian kelebihan beban, karena void* tidak secara implisit dapat dikonversi menjadi int*. Dengan kata lain, Anda tidak dapat mengonversi, bahkan secara eksplisit, shared_ptr<void> ke shared_ptr<T> jika Anda tidak dapat mengonversi void* ke T* secara implisit.

Mengapa tidak menggunakan templat terlebih dahulu (pindahkan fungsionalitas GenericStack ke TStack), daripada mencoba menangani void*?

Namun saya mencoba menggunakan kembali kode sebanyak yang saya bisa, sehingga kelas yang ditemplat tidak terlalu membengkak.

Dengan "membengkak", saya berasumsi maksud Anda solusi templat akan menghasilkan terlalu banyak contoh? Apakah Anda punya alasan untuk percaya bahwa jumlahnya memang terlalu banyak?

person Nelfeal    schedule 25.11.2018