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.
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:
~~~
~~~
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.
Most helpful comment
The recent interfaces cleanup https://github.com/robotology/yarp/pull/1691 fixes this issue. Closing.