Yarp: Order of header inclusion (yarp interfaces) affects functionality

Created on 10 Apr 2018  路  5Comments  路  Source: robotology/yarp

There's some strange loop in the yarp interfaces headers. A simple compilation unit such as:

#include <yarp/dev/IControlMode.h>
#include <yarp/dev/IControlMode2.h>
#include <yarp/dev/ICurrentControl.h>
#include <yarp/dev/IPWMControl.h>
#include <yarp/dev/IPositionControl.h>
#include <yarp/dev/IPositionDirect.h>
#include <yarp/dev/ITorqueControl.h>
#include <yarp/dev/IVelocityControl.h>

fails the following error:

In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:1:
/iit/local/include/yarp/dev/IControlMode.h:25:31: error: no member named 'IControlMode' in namespace 'yarp::dev'
class YARP_dev_API yarp::dev::IControlMode
                   ~~~~~~~~~~~^
/iit/local/include/yarp/dev/IControlMode.h:27:1: error: expected expression
public:
^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:25:82: error: base class has incomplete type
class __attribute__ ((visibility ("default"))) yarp::dev::IControlMode2 : public yarp::dev::IControlMode
                                                                          ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:31:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::setPositionMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:32:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::setVelocityMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:33:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::setTorqueMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:34:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::setImpedancePositionMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:35:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::setImpedanceVelocityMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:37:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::getControlMode;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
In file included from /home/dferigo/git/WB-Toolbox/toolbox/src/testheader.cpp:2:
/iit/local/include/yarp/dev/IControlMode2.h:38:11: error: incomplete type 'yarp::dev::IControlMode' named in nested name specifier
    using IControlMode::getControlModes;
          ^~~~~~~~~~~~~~
/iit/local/include/yarp/dev/IControlMode.h:16:11: note: forward declaration of 'yarp::dev::IControlMode'
    class IControlMode;
          ^
10 errors generated.

Instead, changing the file as follows, it compiles fine:

// Group 1
#include <yarp/dev/ICurrentControl.h>
#include <yarp/dev/IPWMControl.h>
#include <yarp/dev/ITorqueControl.h>

#include <yarp/dev/IControlMode.h>
#include <yarp/dev/IControlMode2.h>

// Group 2
#include <yarp/dev/IPositionControl.h>
#include <yarp/dev/IPositionDirect.h>
#include <yarp/dev/IVelocityControl.h>

As a note, at least one of the Group 1 headers must be before the IControlMode* in order to work. If Group 1 is moved after IControlMode* and any of the lines of the Group 2 headers is moved before IControlMode*, it doesn't compile again.

Library - YARP_dev YARP v3.0.0 Bug Fixed

Most helpful comment

The recent interfaces cleanup https://github.com/robotology/yarp/pull/1691 fixes this issue. Closing.

All 5 comments

As a suggestion to avoid this kind of issues, it is a good practice to have a C++ file for each header file, that includes the header as first include. This ensures that the header does not require other headers to work.

I completely agree. I add that if you use clang-format for formatting the code this is done automatically (https://clang.llvm.org/docs/ClangFormatStyleOptions.html @ IncludeCategories).

I think one of these files headers:
~~~

include

include

include

include

include

include

include

include

~~~
is not a self-sufficient header ( http://www.drdobbs.com/self-sufficient-headers/184401705 ). Compiling a compilation unit containing only the include for each file should highlight which file is not self-sufficient.

We could write some unit test using some cmake magic, that creates a .cpp file for each .h file and tries to compile it...

The recent interfaces cleanup https://github.com/robotology/yarp/pull/1691 fixes this issue. Closing.

Was this page helpful?
0 / 5 - 0 ratings