0

The following has a very strange error:

In a header somewhere I have:

class WCameraPosition : public Widget3D
    {
    public:

        WCameraPosition(double scale = 1.0);
        WCameraPosition(const Matx33d &K, double scale = 1.0, const Color &color = Color::white());
        WCameraPosition(const Vec2d &fov, double scale = 1.0, const Color &color = Color::white());
        WCameraPosition(const Matx33d &K, InputArray image, double scale = 1.0, const Color &color = Color::white());
        WCameraPosition(const Vec2d &fov, InputArray image, double scale = 1.0, const Color &color = Color::white());
    };
class  Widget3D : public Widget
    {
    public:
        Widget3D() {}
    //...
}

typedef Matx<double, 3, 3> Matx33d;

For some reason the following compiles:

WCameraPosition camSymbol1(Matx33d(K));
WCameraPosition camSymbol2(1.0);
Widget w(camSymbol2); 

But this does not:

WCameraPosition camSymbol1(Matx33d(K));
WCameraPosition camSymbol2(1.0);
Widget w(camSymbol1);

I get the error:

error: no matching function for call to ‘Widget3D::Widget3D(
WCameraPosition (&)(Matx33d))’
note: Widget3D::Widget3D(const Widget3D&)
no known conversion for argument 1 from ‘WCameraPosition(Matx33d) 
{aka WCameraPosition(Matx<double, 3, 3>)}’ to 
‘const Widget3D&’

I'm utterly befuddled by this. It is as if a new templated type was created, but WCameraPosition and its superclasses don't even use templates. I need to pass camSymbol1 to functions taking Widget3D&. How do I fix this?

Paul Foster
  • 45
  • 1
  • 1
  • 5

2 Answers2

2

This is a case of the most vexing parse. The compiler thinks that this is a function declaration:

WCameraPosition camSymbol1(Matx33d(K));

Fix it by initializing your object using braces:

WCameraPosition camSymbol1{Matx33d(K)};
Joseph Thomson
  • 9,888
  • 1
  • 34
  • 38
  • Ah! That worked! I see, so it has nothing to do with templates at all, just that I used a type name inside the parens. I'm still trying to work out how that could be a valid function declaration, but I get the idea. – Paul Foster Feb 22 '17 at 06:12
  • 1
    @PaulFoster It's legal to surround variable names with parentheses. This is necessary when declaring things like function pointers (e.g. `void (*f)()`). – Joseph Thomson Feb 22 '17 at 06:15
  • My next thought was "Why is this still allowed in c++11?" since I thought they got rid of the most vexing parse issues, but it turns out that this has the obscure use that you can forward declare a function inside the scope of another function, so the parse has to remain legal. – Paul Foster Feb 22 '17 at 06:26
0
WCameraPosition camSymbol1(Matx33d(K));

Is a function declaration. You ran into the most vexing parse.

Community
  • 1
  • 1
yuri kilochek
  • 12,709
  • 2
  • 32
  • 59