2017-02-23 11 views
10

Próbuję skompilować następujący kod (nieco minimalny przykład), złożyć test.cpp:dzyń: nie można rzutować do prywatnej bazy natomiast jest public virtual dziedziczenie

#include <iostream> 
#include <memory> 

class Shared : public std::enable_shared_from_this<Shared>{ 
public: 
    int prea; 
}; 

class Widget : public virtual Shared{ 
    int a; 
public: 
    ~Widget(){ 
     a = 7; 
    } 
}; 

class Container : virtual public Widget{ 
}; 

class List : private Container, virtual public Widget{ 
public: 
    int c; 
}; 


int main(int argc, char** argv){ 
    auto c = std::make_shared<List>(); 
    c->c = 3; 

    std::cout << c->c << std::endl; 

    return 0; 
} 

Korzystanie clang++ następująco:

clang++ test.cpp -std=c++11 

I to daje mi następujący błąd:

/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/bits/shared_ptr_base.h:1106:50: error: 
     cannot cast 'List' to its private base class 'const enable_shared_from_this<Shared>' 
      __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); 
                 ^

Zobacz pełne wyjście here.

Następnie, jeśli skompiluję ten sam kod przy użyciu g ++, nie wystąpi błąd i zostanie wygenerowany plik wykonywalny. Powiedziałbym, że jest to wynik, jakiego oczekuję. Nie mam pojęcia dlaczego clang ++ nie lubi kodu.

Pytanie brzmi, kto ma rację? clang++ lub g++?

Edit: może być powielana nawet na mniejszych przykład:

#include <iostream> 
#include <memory> 

struct Shared : public std::enable_shared_from_this<Shared>{ 
}; 

struct Container : virtual public Shared{ 
}; 

struct List : private Container, virtual public Shared { 
}; 

int main(int argc, char** argv){ 
    auto c = std::make_shared<List>(); 
    return 0; 
} 
+0

Jestem ciekawa, czy możesz skompilować to ze standardową biblioteką klang? Jak widać, domyślnie clang w systemach * nix używa standardowej biblioteki gcc. Może to błąd, zwłaszcza gdy clang kompiluje standardowy kod biblioteki gcc. Edycja: Szybko przetestowałem to na coliru, wygląda na to, że standardowa biblioteka nie robi różnicy, ale OP może powinieneś to zweryfikować. –

+1

Znacznie mniejszy przypadek repro (rozważ aktualizowanie pytania): http://coliru.stacked-crooked.com/a/56d44d6bf2ce459b –

+1

Działa, jeśli używasz 'Listy klas: wirtualny widget publiczny, prywatny kontener '. – skypjack

Odpowiedz