Mar 3, 2015 at 3:34pm UTC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#include <fstream>
class Item {
public :
virtual Item* createFrom (std::istream&) const = 0;
};
template <typename Derived>
class ItemCRTP : virtual public Item {};
class Ball : virtual public Item {
public :
virtual Ball* createFrom (std::istream&) const = 0;
void load (std::istream&) {}
};
template <typename Derived>
class BallCRTP : virtual public Ball {
protected :
virtual Ball* createFrom (std::istream& is) const override {Derived* derived = new Derived; derived->load(is); return derived;}
};
class SportBall : virtual public Ball {};
class SoccerBall : public SportBall, public ItemCRTP<SoccerBall>, public BallCRTP<SoccerBall> {};
template <typename T>
class SpecialBall : public T, public ItemCRTP<SpecialBall<T>>, public BallCRTP<SpecialBall<T>> {
virtual Ball* createFrom (std::istream& is) const override {return BallCRTP<SpecialBall<T>>::createFrom(is);}
};
int main() {
SoccerBall a
SpecialBall<SoccerBall> b;
}
// Visual Studio 2013: error C2250: 'SpecialBall<SoccerBall>' : ambiguous inheritance of 'Ball *Item::createFrom(std::istream &) const' Line 30
The code runs fine with GCC though. Is there undefined behaviour somewhere? What can I add here so that it compiles on Visual Studio 2013?
Last edited on Mar 3, 2015 at 3:43pm UTC
Mar 3, 2015 at 4:24pm UTC
Last edited on Mar 3, 2015 at 4:25pm UTC
Mar 3, 2015 at 4:45pm UTC
Wow! And Microsoft states that the bug is not fixable either! Then perhaps this is an acceptable workaround? It compiles on Visual Studio now at least. I need the function in the base class and in immediate child classes like Ball.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#include <fstream>
class Item {
public :
virtual Item* create (std::istream&) const = 0; // ***Changed name
};
template <typename Derived>
class ItemCRTP : virtual public Item {
};
class Ball : virtual public Item {
public :
virtual Ball* createFrom (std::istream&) const = 0;
void load (std::istream&) {}
private :
virtual Ball* create (std::istream& is) const override {return createFrom(is);} // ***Added
};
template <typename Derived>
class BallCRTP : virtual public Ball {
protected :
virtual Ball* createFrom (std::istream& is) const override {Derived* derived = new Derived; derived->load(is); return derived;}
};
class SportBall : virtual public Ball {};
class SoccerBall : public SportBall, public ItemCRTP<SoccerBall>, public BallCRTP<SoccerBall> {};
template <typename T>
class SpecialBall : public T, public ItemCRTP<SpecialBall<T>>, public BallCRTP<SpecialBall<T>> {
virtual Ball* createFrom (std::istream& is) const override {return BallCRTP<SpecialBall<T>>::createFrom(is);}
};
int main() {
SoccerBall a;
SpecialBall<SoccerBall> b;
}
Last edited on Mar 3, 2015 at 8:10pm UTC
Mar 3, 2015 at 4:51pm UTC
Actually it is enough to get rid of covariance. Make all createFrom functions return Item* pointer.
Mar 3, 2015 at 4:59pm UTC
Yes, for this sample. I need covariant return types in my actual program. I guess I just have to deal with the inconvenience then.