ไม่สามารถแปลงจาก std::shared_ptr‹_Ty› เป็น std::shared_ptr‹_Ty›

ฉันได้รับข้อผิดพลาดต่อไปนี้:

ข้อผิดพลาด C2440: 'static_cast' : ไม่สามารถแปลงจาก 'std::shared_ptr‹_Ty>' เป็น 'std::shared_ptr‹_Ty> stack\genericstack.h 36 1 Stack

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;
}

Main.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;
}

เหตุใดฉันจึงได้รับข้อผิดพลาด

ฉันคาดหวังว่าการส่งจะเกิดขึ้นได้สำเร็จ เนื่องจากด้วยพอยน์เตอร์แบบดิบ ฉันสามารถเปลี่ยนจาก void* เป็นพอยน์เตอร์ประเภทจริงได้เสมอ

สิ่งที่ฉันต้องการทำที่นี่คือการสร้างเทมเพลตสแต็ก แต่ฉันกำลังพยายามนำโค้ดกลับมาใช้ใหม่ให้ได้มากที่สุด เพื่อที่คลาสที่สร้างเทมเพลตจะได้ไม่ขยายตัวมากเกินไป

ขอบคุณ


person yourbuddy    schedule 25.11.2018    source แหล่งที่มา
comment
ฉันคาดหวังว่าการส่งจะเกิดขึ้นได้สำเร็จ เนื่องจากด้วยพอยน์เตอร์ดิบ ฉันสามารถเปลี่ยนจาก void* เป็นตัวชี้ประเภทจริงได้เสมอ เนื่องจาก std::shared_ptr รักษาความปลอดภัยของประเภท และคุณพยายามที่จะทิ้งสิ่งนั้นไป นอกจากนี้ โปรดทราบว่า สำเร็จ จะป้องกันคุณจากข้อผิดพลาดของคอมไพเลอร์ที่เห็นได้ชัดเท่านั้น และไม่ปลอดภัยเกี่ยวกับ พฤติกรรมที่ไม่ได้กำหนด   -  person πάντα ῥεῖ    schedule 25.11.2018
comment
@ πάνταῥεῖ เป็นไปไม่ได้หรือที่ฉันพยายามทำ?   -  person yourbuddy    schedule 25.11.2018
comment
เป็นไปไม่ได้หรือว่าฉันกำลังพยายามทำอะไร ขึ้นอยู่กับว่าประเภทเหล่านี้เกี่ยวข้องกันอย่างไร   -  person πάντα ῥεῖ    schedule 25.11.2018
comment
Nitpick (ไม่เกี่ยวข้องกับคำถามของคุณ แต่มีความสำคัญทางเทคนิค): การใช้ตัวระบุ _GENERIC_STACK_TROFIMOV_H_ เป็นตัวระบุที่สงวนไว้อย่างเป็นทางการ   -  person curiousguy    schedule 25.11.2018
comment
@ πάνταῥεῖ พวกมันไม่เกี่ยวข้องกัน แต่ทุกครั้งที่มีการแสดงจะมีการรับประกันว่าก่อนหน้านี้จะแทนที่ shared_ptr<void> shared_ptr<T>   -  person yourbuddy    schedule 25.11.2018
comment
@curiousguy ฉันคิดว่าจะไม่ใช้ตัวระบุทุกที่ แต่ขอบคุณ ฉันเข้าใจปัญหาที่คุณกำลังชี้ให้เห็น   -  person yourbuddy    schedule 25.11.2018
comment
static_cast 1) ไม่ใช่ตัวดำเนินการที่โอเวอร์โหลดได้ 2) สำหรับประเภทที่ผู้ใช้กำหนด: สามารถทำได้เฉพาะสิ่งที่การเรียกตัวสร้างสามารถทำได้เท่านั้น   -  person curiousguy    schedule 25.11.2018


คำตอบ (2)


คุณได้รับข้อผิดพลาดดังกล่าวเนื่องจาก static_cast กำหนดให้ประเภท from และ to สามารถแปลงได้ สำหรับ shared_ptr ที่จะระงับเฉพาะในกรณีที่ c'tor overload 9 จะเข้าร่วมเท่านั้น ในความละเอียดโอเวอร์โหลด แต่ไม่ได้เป็นเช่นนั้น เนื่องจาก void* ไม่สามารถแปลงเป็นตัวชี้วัตถุประเภทอื่นใน C++ โดยปริยายได้ จึงจำเป็นต้องมี static_cast ที่ชัดเจน

หากคุณต้องการแปลงพอยน์เตอร์ที่แชร์ตาม static_casting ประเภทพอยน์เตอร์ที่ได้รับการจัดการ คุณต้องใช้ std::static_pointer_cast นั่นคือสิ่งที่มีไว้สำหรับ

ดังนั้นหลังจากเสียบฟิกซ์นั้นแล้ว

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

กระดาษห่อเทมเพลตแบบบางของคุณจะสร้างได้ดี

person StoryTeller - Unslander Monica    schedule 25.11.2018
comment
คุณช่วยฉันแก้ปัญหาอื่นในการแชทได้ไหม - person yourbuddy; 25.11.2018
comment
@yourbuddy - หากคุณมีปัญหาอื่นก็อาจคุ้มค่าที่จะถามคำถามอื่น - person StoryTeller - Unslander Monica; 25.11.2018
comment
นี่ ขอบคุณ - person yourbuddy; 25.11.2018

ดูที่ รายการตัวสร้างสำหรับ shared_ptr คุณกำลังพยายามใช้โอเวอร์โหลด 9 โดยเฉพาะเทมเพลตโอเวอร์โหลดที่มี Y = void และ T = int อย่างไรก็ตาม การโอเวอร์โหลดเทมเพลตนี้ ไม่ได้มีส่วนร่วมในการแก้ไขปัญหาโอเวอร์โหลด เนื่องจาก void* ไม่สามารถแปลง โดยปริยาย เป็น int* ได้ กล่าวอีกนัยหนึ่ง คุณไม่สามารถแปลง shared_ptr<void> เป็น shared_ptr<T> ได้อย่างชัดเจน หากคุณไม่สามารถแปลง void* เป็น T* โดยปริยายได้

ทำไมไม่ใช้เทมเพลตตั้งแต่แรก (ย้ายฟังก์ชัน GenericStack ไปที่ TStack) แทนที่จะพยายามจัดการกับ void*

แต่ฉันกำลังพยายามนำโค้ดกลับมาใช้ใหม่ให้ได้มากที่สุด เพื่อที่คลาสที่สร้างเทมเพลตจะได้ไม่ขยายตัวมากเกินไป

โดย "บวม" ฉันคิดว่าคุณหมายถึงโซลูชันเทมเพลตจะสร้างอินสแตนซ์มากเกินไปใช่ไหม คุณมีเหตุผลใดบ้างที่จะเชื่อได้ว่ามันจะมากเกินไปจริงๆ?

person Nelfeal    schedule 25.11.2018