I would wish to use qt5_wrap_cpp (much faster) than CMake's AUTOMOC feature, but I have a problem. In one of the libraries (other compile fine) some of generated moc files with qt5_wrap_cpp are missing declarations. For instance one of include header generated with AUTOMOC is nearly 7kb long, while moc generated for the same file with qt5_cpp_wrap is only 3kb in size. Because of that my compillation fails with
Sequences/CMakeFiles/Sequences.dir/Events/SequenceEventFactory.cpp.obj: In function `ZN13SequenceEvent7setNameERK7QString':
C:/Projects/p2/Sequences/Events/SequenceEvent.h:20: undefined reference to `SequenceEvent::nameChanged(QString)'
This happends only under Windows, while compilling with MinGW. Under Linux CMake and compillation using qt5_wrap_cpp works fine.
This is the code that des problems:
#include "../Containers/XmlObject.h"
#include "../sequences_global.h"
#include <QUuid>
class SequenceEvent;
typedef SequenceEvent* ( *CreateSequenceEvent )();
class SEQUENCESSHARED_EXPORT SequenceEvent : public XmlObject
{
Q_OBJECT
PRIVATE_PROPERTY( QUuid, id, id, setId, idChanged )
PROPERTY( QString, name, name, setName, nameChanged )
protected:
explicit SequenceEvent( QObject* parent = nullptr );
};
I'm using custom macro for PROPERTY:
#define PROPERTY( type, name, read, write, notify ) \
Q_PROPERTY( type _##name READ read WRITE write NOTIFY notify ) \
private: \
type _##name; \
\
public: \
type read() const \
{ \
return _##name; \
} \
Q_SIGNALS: \
void notify( type name ); \
public slots: \
void write( const type& val ) \
{ \
if ( _##name != val ) \
{ \
_##name = val; \
emit notify( val ); \
} \
}
Anyone could help me solve this puzzle? Thanks in advance.
Solved. I was missing
TARGET ${PROJECT_NAME}
at the end of qt5_wrap_cpp macro.
Related
I was reading an article about mock and fake object from Unity folks and then I saw this code:
FAKE_FUNCTION(GetScriptingManager, ScriptingManager&());
FAKE_FUNCTION macro is defined as:
#define FAKE_FUNCTION(functionName, signature) \
FAKE_FUNCTION_IMPL(functionName, functionName, signature)
And FAKE_FUNCTION_IMPL is defined as:
#define FAKE_FUNCTION_IMPL(localName, functionName, signature) \
struct __Fake ## localName : public ::testing::FakeFunction<signature> \
{ \
__Fake ## localName() \
: ::testing::FakeFunction<signature>(#functionName) {} \
}; \
__Fake ## localName localName
What's the meaning of ScriptingManager&()? I understood that's the argument of a template but I can't recall seeing such construct in C++.
Let's say I have some unspecified type called variant, as well as two functions allowing to convert to/from this type, with the following signature:
struct converter
{
template<typename T>
static variant to(const T&);
template<typename T>
static T from(const variant&);
};
Now, what I'd like to do is create wrappers for arbitrary C++ functions as in the following example:
SomeObject f_unwrapped(const std::string& s, int* x)
{
//... do something with the inputs...
return SomeObject();
}
extern "C" variant f(variant s, variant x)
{
return converter::to<SomeObject>(f_unwrapped(converter::from<std::string>(s), converter::from<int*>(x)));
}
Ideally I'd want the wrapper to be a one-line declaration or macro that would take only the f_unwrapped function and the name f as inputs.
I've tried to wrap the function into a function object, then do the bureaucratic work using variadic templates. While this does work, I don't know how to make the resulting function extern "C".
What is the most idiomatic way of achieving this goal?
If we use the EVAL, helper, Conditional, and map macros from the first two code blocks here.
The map will need to be made more general for our needs.
#define MM1() MM_CALL1
#define MM_NEXT1(Macro,a,...) \
IS_DONE(a)( \
EAT \
, \
OBSTRUCT(COMMA)() OBSTRUCT(MM1)() \
) \
(Macro,a,__VA_ARGS__)
#define MM_CALL1(Macro,a,...) \
Macro(a) \
MM_NEXT1(Macro,__VA_ARGS__)
#define MacroMap1(Macro,...) MM_CALL1(Macro,__VA_ARGS__,DONE)
#define MM2() MM_CALL2
#define MM_NEXT2(Macro,a,...) \
IS_DONE(a)( \
EAT \
, \
OBSTRUCT(COMMA)() OBSTRUCT(MM2)() \
) \
(Macro,a,__VA_ARGS__)
#define MM_CALL2(Macro,a,b,...) \
Macro(a,b) \
MM_NEXT2(Macro,__VA_ARGS__)
#define MacroMap2(Macro,...) MM_CALL2(Macro,__VA_ARGS__,DONE)
We will also want the WithTypes and WithoutTypes from here.
We can define AMACRO to do the job you wanted.
#define AsVariant(param) variant param
#define ConvertFrom(type,param) converter::from<type>(param)
#define HEADDER(type,func,params) type func ##_unwrapped (WithTypes params)
#define WRAPPER(type,func,params) \
extern "C" variant func (OBSTRUCT(MacroMap1)(AsVariant,WithoutTypes params)) \
{ \
return converter::to< type >(func ## _unwrapped( \
MacroMap2(ConvertFrom,IDENT params) \
)); \
}
#define AMACRO(type,func,params) \
EVAL( \
HEADDER(type,func,params); \
WRAPPER(type,func,params) \
HEADDER(type,func,params) \
)
Which will turn this:
AMACRO(SomeObject,f,(const std::string&, s, int*, x))
{
// ... do something with the inputs ...
return SomeObject();
}
Into this (after formatting):
SomeObject f_unwrapped (const std::string& s , int* x );
extern "C" variant f (variant s , variant x )
{
return converter::to<SomeObject>(f_unwrapped(converter::from<const std::string&>(s),converter::from<int*>(x)));
}
SomeObject f_unwrapped (const std::string& s , int* x )
{
return SomeObject();
}
NOTE:
If the const needs removing from the parameter, a conditional, similar to the ISDONE, can be made and added to the ConvertFrom macro.
We're trying to do static analysis using cppcheck for our code base for linux using the jenkins plugin. For some reason, it's finding numerous errors for the following type of thing:
CREATE_DERIVED_EXCEPTION_CLASS(ExceptionOSApiError, 5)
and also for:
CREATE_EXCEPTION_CLASS_DERIVED_FROM_SPECIFIC_BASE(ExceptionFileApiError, ExceptionOSApiError, 6)
Where it's defined as (but not giving an error on the lines):
#define CREATE_DERIVED_EXCEPTION_CLASS( new_exception_name, unique_numeric_code ) \
CREATE_EXCEPTION_CLASS_DERIVED_FROM_SPECIFIC_BASE( new_exception_name, Exception, unique_numeric_code )
#ifdef _IN_EXCEPTION_CPP
#define CREATE_EXCEPTION_CLASS_DERIVED_FROM_SPECIFIC_BASE( new_exception_name, base_exception_name, unique_numeric_code ) \
new_exception_name::new_exception_name( const char *message, LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ) \
: base_exception_name( message, lastError, debugContextWhereThrown ) {} \
new_exception_name::new_exception_name( std::string&& message, LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ) \
: base_exception_name( std::move(message), lastError, debugContextWhereThrown ) {} \
new_exception_name::new_exception_name( LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ) \
: base_exception_name( lastError, debugContextWhereThrown ) {} \
new_exception_name::new_exception_name(new_exception_name&& source) \
: base_exception_name(std::move(source)) {} \
new_exception_name& new_exception_name::operator=(new_exception_name&& rightHandSide) \
{ \
if (this != &rightHandSide) \
{ \
base_exception_name::operator=(std::move(rightHandSide)); \
/* No derived class data members to move */ \
} \
return(*this); \
} \
UTILDLL_EXPORT int new_exception_name::getExceptionTypeByNumericCode() const \
{ \
return( unique_numeric_code ); /* This must be UNIQUE! */ \
}
#else // !_IN_CPEXCEPTION_CPP
#define CREATE_EXCEPTION_CLASS_DERIVED_FROM_SPECIFIC_BASE( new_exception_name, base_exception_name, unique_numeric_code ) \
class UTILDLL_EXPORT new_exception_name : public base_exception_name \
{ \
public: \
new_exception_name( const char *message, LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ); \
new_exception_name( std::string&& message, LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ); \
new_exception_name( LASTERROR_TYPE lastError, const IDebugContext& debugContextWhereThrown ); \
new_exception_name( const new_exception_name& source ) = default; \
new_exception_name& operator=(const new_exception_name& rightHandSide) = default; \
new_exception_name(new_exception_name&& source); \
new_exception_name& operator=(new_exception_name&& rightHandSide); \
virtual ~new_exception_name() = default; \
virtual int getExceptionTypeByNumericCode() const; \
};
#endif // !_IN_EXCEPTION_CPP
Any ideas?
I found this type of info online:
redundant with pragma once
==(It looks like there’s a known problem with cppcheck and #pragma once (#ifndef #define is the fix, but I don’t think we want that). I think we’d see a lot more of this issue if it was #pragma once.
Here’s a second blurb for the redundant code issue:
enum or ifndef for redundant code issue
==(I don’t think it’s an enum issue) (could be that we don’t have #ifndef #define the .h …I don’t see it)
cppcheck thinks I have “Redundant code: Found a statement that begins with numeric constant”
The whole .h file these are defined in just contains the macros and use of the macros. The owner doesn't think he needs a #ifndef around the #define since the cppcheck is complaining about all the lines under the #define that use the macros.
In addition: there is no #ifndef around the whole .h file, but the owner doesn't think it's needed.
Build info:
For our build normally:
g++ -std=c++11 -ggdb -Wall -Wextra -Werror -pedantic -fdiagnostic-show-option -fPIC -DLinuxx86_64
What I'm seeing in jenkins for cppcheck setup:
cppcheck --enable=all --xml --xml-version=2 -DLinuxx86_64 --platform=unix64 --include=Src/Headers/CommonPrecomp.h -v --report-progress -DOPTIMUS_CDECL -DUTILDLL_EXPORT -DOPTIMUS_COREDLL_EXPORT -DREADERDLL_EXPORT -DWRITERDLL_EXPORT -E Src 2> cppcheck.xml
I'm not sure it's doing the build the same in jenkins for cppcheck as it does for our normal build.
Any other ideas? Thanks!
It looks like the issue was that it wasn't getting to our include directories. We had them brought in from a file. We had to add them to the jenkins build setup:
cppcheck -j 2 --xml --xml-version=1 --enable=all -DLinuxx86_64 --platform=unix64 -v --report-progress --suppress=missingIncludeSystem --include=Sr/Head/Common.h -i Sr/Doc/Win.cpp -i Sr/P/S/S.cpp -DOPT_CDECL -DUTILDLL_EXPORT -DOPT_COREDLL_EXPORT -DREADLL_EXPORT -DWDLL_EXPORT -ISr/Head -ISr/Head/libopc -ISr/Head/lib/config -ISrc/Head/lib/lib2 -ISr/Snot -ISr/Doc -ISr/Doc -ISr/PDers/XP -ISr/PDers/Ca -ISr/PDers/Ca/Head -IVersionAndBuildConfig -ISr/Head/GoogleTest/include -ISr/Head/GoogleTest/include/gtest Sr/Doc > cppcheck.xml
Is there a way to generate this kind of macro with some other macro?
E.g. a struct with 3 members or something...
#define CONST_STRUCT2(name, name1, type1, name2, type2) \
struct name \
{ \
name(const type1& p##name1, const type2& p##name2) \
: name1(p##name1), name2(p##name2) {} \
const type1 name1; const type2 name2; \
};
Yes, you can do it with Boost.Preprocessor.
#define CONST_STRUCT(name, members) \
struct name \
{ \
name(GENERATE_CTOR_PARAMS(members)) \
: GENERATE_CTOR_INITIALISERS(members) {} \
GENERATE_MEMBERS(members) \
}
#define PARAM_TYPE(param) \
BOOST_PP_TUPLE_ELEM(2, 0, param)
#define PARAM_NAME(param) \
BOOST_PP_TUPLE_ELEM(2, 1, param)
#define GENERATE_CTOR_PARAMS(members) \
BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(members), GENERATE_CTOR_PARAM, members)
#define GENERATE_CTOR_PARAM(z, idx, members) \
const PARAM_TYPE(BOOST_PP_SEQ_ELEM(idx, members)) & PARAM_NAME(BOOST_PP_SEQ_ELEM(idx, members))
#define GENERATE_CTOR_INITIALISERS(members) \
BOOST_PP_ENUM(BOOST_PP_SEQ_SIZE(members), GENERATE_CTOR_INITIALISER, members)
#define GENERATE_CTOR_INITIALISER(z, idx, members) \
PARAM_NAME(BOOST_PP_SEQ_ELEM(idx, members)) (PARAM_NAME(BOOST_PP_SEQ_ELEM(idx, members)))
#define GENERATE_MEMBERS(members) \
BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(members), GENERATE_MEMBER, members)
#define GENERATE_MEMBER(z, idx, members) \
const PARAM_TYPE(BOOST_PP_SEQ_ELEM(idx, members)) PARAM_NAME(BOOST_PP_SEQ_ELEM(idx, members));
Example of use:
CONST_STRUCT(Three, ((type1, name1))((type2, name2))((type3, name3)));
Necessary header files omitted for clarity. Also, in a real application, choose better scoped names (such as CONST_STRUCT_GENERATE_...).
Is it possible to mix up the BOOST_AUTO_TEST_CASE and BOOST_AUTO_TEST_CASE_TEMPLATE macros with the BOOST_PARAM_TEST_CASE in any way? I'm even interested in really messy ways of making this happen.
Having to build all of your test cases by hand seems really tedious. But the BOOST_PARAM_TEST_CASE mechanism is pretty darn useful, but only works if you have a test init function, which in turn requires you to have be using manual test case construction.
Is there any documentation on how to hook into the automated system yourself so you can provide your own tests that auto-register themselves?
I'm using boost 1.46 right now.
I wrote my own support for this since there really didn't seem to be any good support. This requires the C++11 decltype feature and the ::std::remove_const and ::std::remove_reference library methods to work.
The macro definitions are a modified versions of the BOOST_FIXTURE_TEST_CASE and BOOST_AUTO_TEST_CASE macros.
You use this by declaring your function thus:
BOOST_AUTO_PARAM_TEST_CASE(name, begin, end)
{
BOOST_CHECK_LT(param, 5); // The function will have an argument named 'param'.
}
Here is the header that defines the BOOST_AUTO_PARAM_TEST_CASE macro:
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/parameterized_test.hpp>
#include <type_traits>
#define BOOST_FIXTURE_PARAM_TEST_CASE( test_name, F, mbegin, mend ) \
struct test_name : public F { \
typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \
void test_method(const param_t &); \
}; \
\
void BOOST_AUTO_TC_INVOKER( test_name )(const test_name::param_t ¶m) \
{ \
test_name t; \
t.test_method(param); \
} \
\
BOOST_AUTO_TU_REGISTRAR( test_name )( \
boost::unit_test::make_test_case( \
&BOOST_AUTO_TC_INVOKER( test_name ), #test_name, \
(mbegin), (mend))); \
\
void test_name::test_method(const param_t ¶m) \
// *******
#define BOOST_AUTO_PARAM_TEST_CASE( test_name, mbegin, mend ) \
BOOST_FIXTURE_PARAM_TEST_CASE( test_name, \
BOOST_AUTO_TEST_CASE_FIXTURE, \
mbegin, mend)
The solution provided by #Omnifarious works works, but requires a C++11 compiler.
Adapting that solution for a C++03 compiler:
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/parameterized_test.hpp>
#define BOOST_FIXTURE_PARAM_TEST_CASE( test_name, F, P, mbegin, mend ) \
struct test_name : public F \
{ \
typedef P param_t; \
void test_method(const param_t &); \
}; \
\
void BOOST_AUTO_TC_INVOKER( test_name )(const test_name::param_t ¶m) \
{ \
test_name t; \
t.test_method(param); \
} \
\
BOOST_AUTO_TU_REGISTRAR( test_name )( \
boost::unit_test::make_test_case( \
&BOOST_AUTO_TC_INVOKER( test_name ), #test_name, \
(mbegin), (mend))); \
\
void test_name::test_method(const param_t ¶m) \
// *******
#define BOOST_AUTO_PARAM_TEST_CASE( test_name, param_type, mbegin, mend ) \
BOOST_FIXTURE_PARAM_TEST_CASE( test_name, \
BOOST_AUTO_TEST_CASE_FIXTURE, \
param_type, \
mbegin, mend)
This solution is slightly different is usage. Since there is no declspec in C++03, the type of the parameter object cannot be automatically deduced. We must pass it in as a parameter to BOOST_AUTO_PARAM_TEST_CASE:
class FooTestParam
{
public:
std::string mS;
FooTestParam (int n)
{
std::stringstream ss;
ss << n;
mS = ss.str();
}
};
FooTestParam fooParams [] =
{
FooTestParam (42),
FooTestParam (314)
};
BOOST_AUTO_PARAM_TEST_CASE (TestFoo, FooTestParam, fooParams, fooParams + 2)
{
const std::string testVal = param.mS;
}
BOOST_AUTO_TEST_CASE (TestAddressField)
{
const uint32_t raw = 0x0100007f; // 127.0.0.1
const uint8_t expected[4] = {127, 0, 0, 1};
const Mdi::AddressField& field = *reinterpret_cast <const Mdi::AddressField*> (&raw);
for (size_t i = 0; i < 4; ++i)
BOOST_CHECK_EQUAL (field[i], expected[i]);
}
Starting with Boost version 1.59, this is being handled by data-driven test cases:
#define BOOST_TEST_MODULE MainTest
#include <boost/test/included/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/array.hpp>
static const boost::array< int, 4 > DATA{ 1, 3, 4, 5 };
BOOST_DATA_TEST_CASE( Foo, DATA )
{
BOOST_TEST( sample % 2 );
}
This functionality requires C++11 support from compiler and library, and does not work inside a BOOST_AUTO_TEST_SUITE.
If you have to support both old and new versions of Boost in your source, and / or pre-C++11 compilers, check out And-y's answer.
You can easily mix manual and automated test unit registration. Implement your own init function (like in example 20 on this page) and inside init function you can perform registration for parameterized test cases. Boost.Test will merge them both into single test tree.
Since Boost 1.59 internal details of realization was changed and Omnifarious's solution doesn't compile.
Reason ot that is changing signature of boost::unit_test::make_test_case function: now it take 2 additional args: __FILE__, __LINE__
Fixed solution:
#if BOOST_VERSION > 105800
#define MY_BOOST_TEST_ADD_ARGS __FILE__, __LINE__,
#define MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR ,boost::unit_test::decorator::collector::instance()
#else
#define MY_BOOST_TEST_ADD_ARGS
#define MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR
#endif
#define BOOST_FIXTURE_PARAM_TEST_CASE( test_name, F, mbegin, mend ) \
struct test_name : public F { \
typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \
void test_method(const param_t &); \
}; \
\
void BOOST_AUTO_TC_INVOKER( test_name )(const test_name::param_t ¶m) \
{ \
test_name t; \
t.test_method(param); \
} \
\
BOOST_AUTO_TU_REGISTRAR( test_name )( \
boost::unit_test::make_test_case( \
&BOOST_AUTO_TC_INVOKER( test_name ), #test_name, \
MY_BOOST_TEST_ADD_ARGS \
(mbegin), (mend)) \
MY_BOOST_TEST_DEFAULT_DEC_COLLECTOR); \
\
void test_name::test_method(const param_t ¶m) \
#define BOOST_AUTO_PARAM_TEST_CASE( test_name, mbegin, mend ) \
BOOST_FIXTURE_PARAM_TEST_CASE( test_name, \
BOOST_AUTO_TEST_CASE_FIXTURE, \
mbegin, mend)
I took Omnifarious' header file and modified it such that the parameter is passed to the constructor of the test fixture rather than to the test method. This requires the test fixture's constructor declaration to take a single argument with the parameter's type. I found this to be super handy--much thanks for the initial question and answer!
#include <boost/test/unit_test_suite.hpp>
#include <boost/test/parameterized_test.hpp>
#include <type_traits>
#define BOOST_FIXTURE_PARAM_TEST_CASE( test_name, F, mbegin, mend ) \
struct test_name : public F { \
typedef ::std::remove_const< ::std::remove_reference< decltype(*(mbegin)) >::type>::type param_t; \
test_name(const param_t ¶m) : F(param) {} \
void test_method(void); \
}; \
\
void BOOST_AUTO_TC_INVOKER( test_name )(const test_name::param_t ¶m)\
{ \
test_name t(param); \
t.test_method(); \
} \
\
BOOST_AUTO_TU_REGISTRAR( test_name )( \
boost::unit_test::make_test_case( \
&BOOST_AUTO_TC_INVOKER( test_name ), #test_name, \
(mbegin), (mend))); \
\
void test_name::test_method(void) \
// *******
#define BOOST_AUTO_PARAM_TEST_CASE( test_name, mbegin, mend ) \
BOOST_FIXTURE_PARAM_TEST_CASE( test_name, \
BOOST_AUTO_TEST_CASE_FIXTURE, \
mbegin, mend)