QT C++ forward-declaration problem? - c++

I am trying to use QTPropertyBrowser to edit properties in my QObjects.
From QT Solutions "QtPropertyBrowser" example I use following files in my project.
http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.cpp
http://qt.gitorious.org/qt-solutions/qt-solutions/blobs/master/qtpropertybrowser/examples/object_controller/objectcontroller.h
I configure my CMakeFile as follows :
#include_directories("/usr/include")
SET(QTVIEW_SRCS
src/main.cpp
src/TestWidget.cpp
src/plugin/IPlugin.cpp
src/objectcontroller.cpp
)
SET(QTVIEW_MOH_HDRS
src/TestWidget.h
src/plugin/IPlugin.h
src/objectcontroller.h
)
When I compile the files as they are, compiler giving error as follows -
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:
In member function 'virtual int
ObjectController::qt_metacall(QMetaObject::Call,
int, void**)' :
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: invalid use of incomplete type
'struct ObjectControllerPrivate'
C:\svn\osaka3d\trunk\osaka3d\QTView\src/objectcontroller.h:45:
error: forward declaration of 'struct
ObjectControllerPrivate'
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: expected type-specifier before
'QtProperty'
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: expected '>' before
'QtProperty'
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: expected '(' before
'QtProperty'
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: 'QtProperty' was not declared
in this scope
C:\svn\osaka3d\trunk\osaka3d\QTView\src\moc_objectcontroller.cxx:73:
error: expected primary-expression
before ')' token mingw32-make2: *
[CMakeFiles/qtview.dir/src/moc_objectcontroller.cxx.obj]
Error 1 mingw32-make1:
[CMakeFiles/qtview.dir/all] Error 2
mingw32-make: ** [all] Error 2
But when I comment out the line :
Q_PRIVATE_SLOT(d_func(), void slotValueChanged(QtProperty *, const QVariant &))
in "objectcontroller.h"
and comment out the line :
#include "moc_objectcontroller.cxx"
and the end of file "objectcontroller.cpp" , it compiles well But i cannot use SIGNALS/SLOTs to reflect editing of QObject parameters.
Any tips?

I ran into the same problem (I am new to qt, but this worked for me). For other people searching a solution I found this:
What is happening
The issue is that due to Q_PRIVATE_SLOT macro the generated moc_XXX.cxx needs the full declaration of the XXXPrivate class to call the private slot function. As the public header only forward declares it, the generated cxx can not be compiled on its own. The QtPropertyBrowser guys circumvented this problem by including the generated moc_XXX.cpp (mind the 'pp', cmake generates 'xx')) in their source file (ugly, but works). I also do not know any other way to tell the moc to include (the in this case even not present) private XXX_p.hpp. So let's stick to that way.
What I did next was to remove the generated moc_XXX.cxx files from the executable, but this resulted in the moc never being called. This happened even though I used QT4_WRAP_CPP. So after further searching I found...
One addendum to this special case: the QtProperty declaration is missing. Either add the following forward declaration or the appropriate include file:
#if QT_VERSION >= 0x040400
QT_BEGIN_NAMESPACE
#endif
class QtProperty;
#if QT_VERSION >= 0x040400
QT_END_NAMESPACE
#endif
Solution
Full credit goes to fullmetalcoder who presented this cmake function:
function(qt4_wrap_hdrs _moc_srcs)
qt4_get_moc_flags(_moc_incs)
set(_mocs)
foreach(_current_file ${ARGN})
get_filename_component(_abs_file ${_current_file} ABSOLUTE)
if(EXISTS ${_abs_file})
file(READ ${_abs_file} _contents)
get_filename_component(_basename ${_abs_file} NAME_WE)
string(REGEX MATCH "Q_OBJECT" _match "${_contents}")
if(_match)
set(_moc "${CMAKE_CURRENT_BINARY_DIR}/moc_${_basename}.cpp")
qt4_create_moc_command(${_abs_file} ${_moc} "${_moc_incs}" "")
macro_add_file_dependencies(${_abs_file} ${_moc})
list(APPEND _mocs ${_moc})
endif(_match)
endif(EXISTS ${_abs_file})
endforeach (_current_file)
set(${_moc_srcs} ${_mocs} PARENT_SCOPE)
endfunction(qt4_wrap_hdrs)
(from http://www.qtcentre.org/threads/37428-using-QT-unit-testing-with-CMake)
You can use this function as a drop-in replacement for QT4_WRAP_CPP. You now only need to add the following line into your CMakeLists.txt so that the compiler finds the generated moc_XXX.cpp files (the new function created a 'pp' file...):
include_directories(${CMAKE_BINARY_DIR})
This function calls the moc all the time and behaves more like as in the qmake case. Except of course that you can easily do out of source builds.
But there is one caveat: all moc_XXX.cpp files are generated in the CMAKE_BINARY_DIR. So if you have two files include1/foo.hpp and include2/foo.hpp one will be overwritten!

Have you read the following article about using Qt and CMake together?
http://developer.qt.nokia.com/quarterly/view/using_cmake_to_build_qt_projects
Maybe you're forgetting something, like calling QT4_WRAP_CPP on your CMakeLists.txt.

Related

Why am I getting this error with MinGW and Cmake?

So I am trying to compile this flip fluids addon with blender, so I followed this tutorial, https://www.youtube.com/watch?v=TVKM1egDoGs , So I first ran cmake.exe -G "MinGW Makefiles" .. and it was telling me that it was missing a CMakeLists File... So I added one... then I ran cmake.exe --build . and it got to 3 percent than showed me errors like ...
In file included from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/threadutils.h:29,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/meshlevelset.h:65,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/meshobject.h:30,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/fluidsimulation.h:38,
from C:\Users\N\Downloads\Blender-FLIP-Fluids-master\src\engine\c_bindings\fluidsimulation_c.cpp:25:
C:/PROGRA~2/MINGW-~1/I686-8~1.0-P/mingw32/lib/gcc/i686-w64-mingw32/8.1.0/include/c++/mutex:93:9: note: previous definition of 'class std::recursive_mutex'
class recursive_mutex : private __recursive_mutex_base
^~~~~~~~~~~~~~~
In file included from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/mingw32_threads/mingw.condition_variable.h:25,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/threadutils.h:31,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/meshlevelset.h:65,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/meshobject.h:30,
from C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/fluidsimulation.h:38,
from C:\Users\N\Downloads\Blender-FLIP-Fluids-master\src\engine\c_bindings\fluidsimulation_c.cpp:25:
C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/mingw32_threads/mingw.mutex.h:142:44: error: conflicting declaration 'typedef class std::_NonRecursive<std::recursive_mutex> std::mutex'
This is the full error https://pastebin.com/KTnALG1E, where is this coming from?? is it a mingw error or what? Can someone help please?
Your full error message includes a more interesting bit:
C:/Users/N/Downloads/Blender-FLIP-Fluids-master/src/engine/mingw32_threads/mingw.thread.h:32:2:
error: #error This version of MinGW seems to include a win32 port of
pthreads, and probably already has C++11 std threading classes
implemented, based on pthreads. It is likely that you will get class
redefinition errors below, and unfortunately this implementation can
not be used standalone and independent of the system header,
since it relies on it for std::unique_lock and other utility classes.
If you would still like to use this implementation (as it is more
lightweight), you have to edit the c++-config.h system header of your
MinGW to not define _GLIBCXX_HAS_GTHREADS. This will prevent system
headers from defining actual threading classes while still defining
the necessary utility classes.
So either install a different version of mingw or edit your mingw files according to the instructions above.

Message "error: use of undeclared identifier 'assert'"

I had a piece of code that was including some Boost headers. Upon compilation I received errors like
/usr/local/include/boost/smart_ptr/shared_ptr.hpp:1041:9: error: use of undeclared identifier 'assert'
BOOST_ASSERT( deleter_.use_count() <= 1 );
^
/usr/local/include/boost/assert.hpp:60:29: note: expanded from macro 'BOOST_ASSERT'
# define BOOST_ASSERT(expr) assert(expr)
^
These errors however only occurred on Windows and macOS.
Explicitly including either <cassert> or <assert.h> before the Boost headers had no effect.
You need to #include <cassert> to bring in the assert implementation.
It's your job to define or not define NDEBUG accordingly.
I'm surprised Boost doesn't do that for you - are you using the Boost files correctly (i.e. including the files that you're supposed to)?
As it turned out I had a file called Assert.h in my include-path (a custom file of mine). On case-insensitive file systems as used by Windows and macOS, this would shadow the original assert.h header that actually defines the assert macro.
The solution therefore was simply to rename my assert-header file.
(I found the solution thanks to [Compilation Error] error: use of undeclared identifier 'assert' #15.)

Can't figure out how to get CMake to pull in the correct headers for a custom clang driver

CMake is giving me a real hard time, here. I checked out llvm, clang, and extras, and I created a custom driver folder, added it to the llvm\tools\clang\tools\extra\CMakeLists.txt and created my own CMakeLists.txt:
cmake_minimum_required(VERSION 3.8)
set(LLVM_LINK_COMPONENTS
Support
)
set(CMAKE_CXX_FLAGS ${LLVM_CONFIG})
set(CMAKE_CXX_COMPILER "clang++")
add_clang_executable(mydriver
main.cpp
)
set(CLANG_LIBS clangFrontend clangDriver clangSerialization clangParse
clangCodeGen clangSema clangAnalysis clangEdit clangAST clangLex
clangBasic )
target_link_libraries(mydriver ${CLANG_LIBS})
target_link_libraries(mydriver ${LLVM_LIBS})
CMake works fine. I target VS2017 and build the mydriver project with msbuild
λ msbuild tools\clang\tools\extra\mydriver\mydriver.vcxproj
This results in the following error:
"C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj" (default target) (1) ->
(ClCompile target) ->
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(45): error C2027: use of undefined type 'clang::Preprocessor Options' [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(45): error C2228: left of '.addRemappedFile' must have class /struct/union [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
C:\dev\llvm\tools\clang\tools\extra\mydriver\main.cpp(50): error C2664: 'void clang::CompilerInstance::setInvocati on(std::shared_ptr<clang::CompilerInvocation>)': cannot convert argument 1 from 'clang::CompilerInvocation *' to 'st d::shared_ptr<clang::CompilerInvocation>' [C:\dev\llvm-build\tools\clang\tools\extra\mydriver\mydriver.vcxproj]
However, clangLex is clearly included in the CLANG_LIBS variable in my CMakeLists.txt. The documentation of the clang::PreprocessorOptions class seems to indicate that I have the right libs included.
Any ideas?
Please note that this question is closely related to this one:
Generate assembly from C code in memory using libclang
In classic SO fashion, the problem was that the include file had migrated since the example was posted. The clang documentation requires a new header file, that is, in fact, in the include path. All I needed was:
#include <clang/Lex/PreprocessorOptions.h>
Sorry folks, nothing to see here.

G++ not finding symbols from regex system header

I am trying to use the GNU C library regex functionality in my C++ project, particularly I'm trying to use the regex_t regcomp, regexec, regfree functions. Upon compilation I get errors stating that these symbols are undefined:
me> g++ -I/me/myheaders/ -c RootGenerator.cpp -o RootGenerator.o -std=gnu++0x -Wall
RootGenerator.cpp: In function ‘std::string findFirstFileInCurrentDirectory(std::string)’:
RootGenerator.cpp:1072: error: ‘regex_t’ was not declared in this scope
RootGenerator.cpp:1072: error: expected ‘;’ before ‘re’
RootGenerator.cpp:1073: error: ‘re’ was not declared in this scope
RootGenerator.cpp:1073: error: ‘REG_EXTENDED’ was not declared in this scope
RootGenerator.cpp:1073: error: ‘REG_NOSUB’ was not declared in this scope
RootGenerator.cpp:1073: error: ‘regcomp’ was not declared in this scope
RootGenerator.cpp:1074: error: expected ‘;’ before ‘int’
RootGenerator.cpp:1084: error: ‘status’ was not declared in this scope
RootGenerator.cpp:1084: error: ‘regexec’ was not declared in this scope
RootGenerator.cpp:1092: error: ‘REG_NOMATCH’ was not declared in this scope
RootGenerator.cpp:1108: error: ‘regfree’ was not declared in this scope
I realize that the regex header is a TR1 implementation and is therefore experimental for my version of GCC. I added the -std=gnu++0x compiler option according to the compiler warning recieved when first trying to compile but this doesn't seem to fix the issue. Is this an issue of the system not recognizing and adding paths to "experimental" headers? Are there additional include paths or compiler options that I need to specify?
As an additional note, I noticed in Eclipse/CDT that under the "includes" tab in the Project Explorer view, it shows a list of the system header paths. It lists many header files under the /user/include/c++/4.4.4 path tab, but It doesn't list the regex header. I think this is also reaffirming that there is a setting issue.
Found the problem:
#include <regex>
should be
#include <regex.h>
The regex.h header is the GNU C library implementation of regex, containing the functions I was trying to use in my source. The regex header is the TR1 (and incomplete) regex implemntation. So #Oli, I wasn't referencing the relevant header after all!

Compiling boost::math's Performance Test Application

Has anyone successfully compiled the performance test application for boost::math library?
link: http://www.boost.org/doc/libs/1_50_0/libs/math/doc/sf_and_dist/html/math_toolkit/perf/perf_test_app.html
I tried compiling by running b2 in the directory and there were lots of errors (over 222000 lines).
First few lines of errors:
../test/erf_data.ipp:6:74: error: wrong number of template arguments (1, should be 2)
In file included from ../../../boost/math/tools/rational.hpp:13:0,
from ../../../boost/math/special_functions/log1p.hpp:18,
from ../../../boost/math/special_functions/gamma.hpp:35,
from test_erf.cpp:9:
../../../boost/array.hpp:60:11: error: provided for ‘template<class T, long unsigned int N> class boost::array’
In file included from test_erf.cpp:13:0:
../test/erf_data.ipp:6:80: error: template argument 1 is invalid
../test/erf_data.ipp:6:91: error: invalid type in declaration before ‘=’ token
../test/erf_data.ipp:7:38: error: ‘SC_’ was not declared in this scope
../test/erf_data.ipp:7:88: error: ‘SC_’ was not declared in this scope
In file included from test_erf.cpp:13:0:
../test/erf_data.ipp:7:136: error: ‘SC_’ was not declared in this scope
Alright, I got it to compile and link properly but it was not with b2. I know the OP asked for b2 but im not familiar with it so i am providing an alternative. This solution assumes you have Cmake installed. (easy to do, just ask dr google.)
If you go to the math tests location:
~/pathToBoost/libs/math/performance
and you add a file called:
CMakeLists.txt
with the following Contents:
cmake_minimum_required(VERSION 2.8)
find_package(Boost COMPONENTS REQUIRED)
include_directories(${DEPENDENCY_DIR}/libboost/lib)
add_executable(main main.cpp test_reference.cpp)
target_link_libraries (main ${Boost_LIBRARIES} boost_regex)
Then you make a folder called build:
mkdir build
And build it.
cd build
cmake ..
make
Doing this got me successful compilation and building. I get a program called main out of it.
Hope this helps.