2

It's a mouthful to describe the problem with words, in code it's much simpler:

template <typename T>
struct Vec2
{
    Vec2() = default;
    Vec2(const Vec2&) = default;
};

template <class T>
struct Point : public Vec2<T>
{
    using Vec2<T>::Vec2;
};

void f(const Point<float>&);

void test()
{
    f(Vec2<float>{});
}
  • Vec2<T> has a copy constructor.
  • Point<float> is derived from Vec2<float> and pulls in its constructors.

Expected: Point<float> should be constructible from Vec2<float>.
Reality: "No known conversion" error (https://godbolt.org/z/boe86f99K). Why?

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • 1
    It's not clear why `Vec2f` is a class at all. Why not use `Vec2` or just a typedef? – Spencer May 16 '22 at 19:32
  • `f()` takes in a reference to a `Vec2f`, but you are passing it a `Point` instead. `Point` does not derive from `Vec2f`, it derives from `Vec2` instead, which is not the same type as `Vec2f`. – Remy Lebeau May 16 '22 at 19:44
  • 1
    Are you expecting that two classes derived from the same class are convertible from each other because they, ehm, *"pull in the constructors"* of the base class? – MatG May 16 '22 at 19:48
  • @Spencer: it's a class because it defines some extra behavior that's special for floats. – Violet Giraffe May 16 '22 at 19:50
  • @MatG: What I expect is described by the 3 bullet points in my question. I expect that `Vec2f` should be constructible from `Vec2`, and it does not seem to be the case. – Violet Giraffe May 16 '22 at 19:51
  • @VioletGiraffe See [Inheriting constructors](https://stackoverflow.com/questions/347358/inheriting-constructors), particularly [this answer](https://stackoverflow.com/a/68180595/65863), which allows your code to compile (if you ignore some side effects) - you can even get rid of the type-cast in the `f()` call ([Demo](https://godbolt.org/z/zT9zjKbx8)) – Remy Lebeau May 16 '22 at 19:55
  • @RemyLebeau: I know that constructors are not inherited. The answer you suggested is a bit odd, and I know this would work if I manually define the conversion constructor, but I don't want to do that. Why doesn't this answer work in my case? https://stackoverflow.com/a/434784/634821 – Violet Giraffe May 16 '22 at 20:01
  • @VioletGiraffe So, why not an explicit specialization on `float`? – Spencer May 16 '22 at 20:12
  • @VioletGiraffe "*Why doesn't this answer work in my case?*" - I can't answer that. Either it is a limitation of the standard, or a bug in the compiler. But explicitly declaring the appropriate forwarding constructors works: [demo](https://godbolt.org/z/3vvWxMEqn) – Remy Lebeau May 16 '22 at 20:13
  • @RemyLebeau: all 3 compilers agree, so it's very unlikely a compiler error. – Violet Giraffe May 16 '22 at 20:15
  • @Spencer: because then I would have to redefine everything instead of just redefining 1 method of the 20 methods of the base class. – Violet Giraffe May 16 '22 at 20:15
  • @VioletGiraffe Maybe there is some information at https://en.cppreference.com/w/cpp/language/using_declaration that explains your situation? – Remy Lebeau May 16 '22 at 20:18

0 Answers0