Why use macro in the class declaration - c++

I am reading the source code of leveldb, esp. regarding mutexlock.
I found this declaration:
class SCOPED_LOCKABLE MutexLock {
public:
explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->Lock();
}
~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
private:
port::Mutex *const mu_;
// No copying allowed
MutexLock(const MutexLock&);
void operator=(const MutexLock&);
};
and I found that SCOPED_LOCKABLE is defined as empty, so why use it in the class declaration?

In class or function definitions if developer need to attach extra characteristic it uses MACROS than hard coding in each class or function definitions. This is a good practice for programming. because one day if you need to change this characteristic you have to change in only one place not everywhere of the code.
Some usage of macros in class definition
#ifdef CONTROLLER_EXPORTS
#define CONTROLLER_API __declspec(dllexport)
#else
#define CONTROLLER_API __declspec(dllimport)
#endif
class CONTROLLER_API CConfiguration{
} ;
You can get some more windows related useful clues here. http://msdn.microsoft.com/en-us/library/dabb5z75(v=vs.80).aspx
Even you can use access modifiers also like this, because some time for testing you may need to change the access level temporary.
#define PRIVATE private
#define PUBLIC public
class A{
PRIVATE:
int m_a;
PUBLIC:
int m_b;
}
Then what is exact your issue? it can be any useful characteristic define like above. here is one example i got from git
#define SCOPED_LOCKABLE __attribute__ ((scoped_lockable))
For details about __attribute__ check here
For the source I got above code check here

It might be defined as something different in a different environment. Sometimes it can affect linkage.
It can also indicate that other headers need to be included to make the library headers properly configured.

Related

How to define a macro that resolves to either method name or no operation?

In the code base I have many sections that are either turned on or off depending on enabled features. The aim is to generate program code as small as possible (Arduino with 32kB program memory).
Lets say I have the code as below:
class A
{
private:
#ifdef FEATURE
int m_optA;
int m_optB;
#endif
public:
#ifdef FEATURE
void SetFeatureOptions(int optionA, int optionB)
{
m_optA = optionA;
m_optB = optionB;
}
#endif
};
#ifdef FEATURE
#define SETFEATUREOPTIONS(a, b) SetFeatureOptions(a, b)
#else
#define SETFEATUREOPTIONS(a, b) Noop() // ????? <-- what should I put here to perform NOOP
#endif
class B
{
public:
A m_a;
void DoStuff()
{
// approach 1:
#ifdef FEATURE
m_a.SetFeatureOptions(1, 34);
#endif
// approach 2:
// Lets have a macro - see above
// This way each time I want to call SetFeatureOptions but only when FEATURE is defined
// I need no ifdef/endif scope to be used explicitely.
m_a.SETFEATUREOPTIONS(1, 34);
}
}
Is there a way to resolve SETFEATUREOPTIONS macro so it compiles and yet doesn't generate any code, when called as a method name?
Why way is to implement Noop() method in class A, but I was wondering if there is better way, that is not requiring adding a null method like mentioned above Noop(). I am not sure if adding inline Noop(){} will add some bytes to the program memory or not (Release, optimized code).
IMPORTANT: This has to compile with C++98 compiler.
Just write:
void SetFeatureOptions(int optionA, int optionB)
{
#ifdef FEATURE
m_optA = optionA;
m_optB = optionB;
#endif
}
and make sure you compile with optimizations turned on. Your compiler is smart enough to delete the function call, if the function is defined in the header file and is empty.
If the function is defined in a different .cpp file the compiler won't know it's empty, so it won't delete the call.

C++ reserved symbol as C variable name

I'm using an external C library inside a C++ project.
The header contains a struct with a variable named class:
#ifdef __cplusplus
extern "C" {
#endif
struct something_t {
...
sometype class;
};
#ifdef __cplusplus
}
#endif
g++ does not like this and complains about "error: expected identifier before ';' token".
What options do I have?
I could rename class, but that's cumbersome and breaks upstream compatibility.
I could ask the upstream project to rename the variable, but that may be difficult.
I could redefine class in the header using the preprocessor: #define class class_ Are there any side effects?
Any other suggestions?
What's the best way to handle this situation?
Result: Based on the prevailing preference for option 2, I finally chose to initiate a renaming in the upstream library.
As others already mentioned in comments, the best option is to write another C API layer around that stuff, that uses the other API only internally.
Anything related to this offending struct definition should be exported through opaque pointers only.
In C++ you can use the cleaned up C-API then.
Here's a small sketch:
ThirdParty.h (contains offending code to compile with c++)
#ifdef __cplusplus
extern "C" {
#endif
struct something_t {
...
sometype class;
};
struct something_t* CreateSomething(); // Does memory allocation and initialization
void DoSomething(struct something_t* something);
#ifdef __cplusplus
}
#endif
MyApiWrapper.h
#ifdef __cplusplus
extern "C" {
#endif
typedef void* psomething_t;
struct psomething_t MyCreateSomething(); // Does memory allocation and initialization
void MyDoSomething(psomething_t something);
#ifdef __cplusplus
}
#endif
MyApiWrapper.c
#include "ThirdParty.h"
struct psomething_t MyCreateSomething() {
psomething_t psomething = (psomething_t)CreateSomething();
return psomething;
}
void MyDoSomething(psomething_t something) {
DoSomething((struct something_t*)psomething);
}
Regarding your considered solutions
I could ask the upstream project to rename the variable, but that may be difficult
You certainly should report that bug to let them know. If it's a git-hub hosted project prepare a pull request.
Anyways be prepared that they might not be responsive timely, and you should always have the above mentioned "plan B". It will work regardless ...
I could redefine class in the header using the preprocessor: #define class class_ Are there any side effects?
It could be a viable way, if any place where this particular symbol (class) appears is plain c code and no other parts of the 3rd party c code (e.g. as library) depends on that symbol (which is unlikely).

Variadic Macros

I came across this code that involved variadic Macros and I wanted to know what that meant
#define DECLARE_LEGACY_TYPES(...) //This all of the macro - I am not holding out on anything
Now There is this class as this
Header file: .h
namespace LG_Wrapper
{
template <LG_Thread Thread>
class EffectApplication : public ktApplication
{
public:
static EffectApplication<Thread>& GetInstance();
protected:
.....
.....
static boost::recursive_mutex mResource;
}
}
DECLARE_LEGACY_TYPES(EffectApplication); <---- What does this do ?
I wanted to know what effect the macro has ?
Update:
I have received numerous downvotes on this as this question gives of the impression that something is missing that I did not post the entire content of the macro. There is nothing more to the macro. I wish there was. This question is related to this which was closed. The macro literally just ends after (...)
#define DECLARE_LEGACY_TYPES(...)
but there isnt. That is one of the reason why I am here as I am not sure how to deal with this situation. Does this macro have not effect then ?
More Info:
This is what I have in another file
I am using the following defined in my project setting
LG_WRAPPER_EXPORTS
LG_THREAD_NAME=GAME
Following is the code
namespace LG_Wrapper
{
enum LG_Thread
{
GAME,
OTHER
};
/*
If the library itself is including this file
*/
#ifdef LG_WRAPPER_EXPORTS
#ifndef LG_THREAD_NAME
#error You must define LG_THREAD_NAME!
#endif
//Legacy types should not be used internally
#define DECLARE_LEGACY_TYPES(...)
#else // LG_WRAPPER_EXPORTS
//Legacy typenames are provided for convenience to the client
#define DECLARE_LEGACY_TYPES(ClassType) \
typedef LG_Wrapper::##ClassType##<LG_Wrapper::GAME> ClassType; \
#endif // LG_WRAPPER_EXPORTS
}
This is actually pretty common, but it depends on other code that wasn't mentioned in the other code you looked at:
#if USING_OLD_COMPILER //when using an older compiler, use this to declare legacy types
#define DECLARE_LEGACY_TYPES(...) STUFF(__VA_ARGS__)
#else //new compiler doesn't have to do anything special
#define DECLARE_LEGACY_TYPES(...)
#endif
//in older compilers we had to declare legacy types for this
//newer compilers don't need this step, so this does nothing at all in them.
DECLARE_LEGACY_TYPES(EffectApplication);
I don't actually know this macro, so I don't know it's actual purpose. But it's common to see macros without definitions for similar tricks as this.

Why does marking an enum as exported/imported break Doxygen generation?

Using Doxygen, I stumbled across this warning:
D:/<some/path>/Camera.h:20: warning: documented symbol `enum DLLPORT
ct::CameraCapture::ct::CameraCapture::CamType' was not declared or defined.
Now I know why Doxygen does not find that class (the namespaces are obviously duplicated), what I don't understand is why it is even searching for it. This enum is in a header file, directly above a class definition, and the class is found fine, it also doesn't get those double namespaces generated.
The source code compiles, too, so it probably isn't a syntactic error that is causing Doxygen these problems.
Specifically, the source code looks like this:
#ifdef CT_EXPORTS
#define DLLPORT __declspec(dllexport)
#else
#define DLLPORT __declspec(dllimport)
#endif
#include <somelibrary>
namespace ct {
namespace CameraCapture {
/**The type of camera used:
*[...]
**/
enum DLLPORT CamType {
CT_ENUM1=0,
CT_ENUM2,
CT_ENUM3,
CT_NONE
};
/**\brief A parent-class to cameras of all types.
*[...]
**/
class DLLPORT Camera
{
//...some content...
};
}
}
This same problem occurs with other enum blocks, too.
Hopefully some of you guys know what is happening there.
Cheers
You don't need to dllexport nor dllimport enums. They're mere declarations of a type, not of code. Just use enum CamType. Classes (either en'masse or by-member) will need it, as will individual free functions, but simple enums do NOT.

C++ __declspec( dllexport ) functions cannot access instance variables

I am trying to protect some C++ code by exporting as a DLL (on Windows/VS 2010).
In the example below var is set in the superclass constructor, and the debugger shows it is definitely set to reference something.
Test is constructed in the code that consumes the DLL the Test class is contained within.
But when go is called from on an instance of test (invoked from the DLL, but the invoking method is called by the DLL consumer) var is a null pointer (it's value is 0).
This is a simplification as I am not allowed to share the actual code.
//Headers
class Base {
public:
__declspec(dllexport) Base();
private:
Foo* var;
};
class Test : Base {
public:
__declspec(dllexport) Test();
__declspec(dllexport) void go();
private:
};
//Body
Base::Base() {
var = new Foo();
}
Test::Test() : Base() {
}
void Test::go() {
var->do_something();
}
In the consuming code, the header is
class Base {
public:
__declspec(dllimport) Base();
};
class Test {
public:
__declspec(dllimport) Test();
__declspec(dllimport) void go();
};
The actual code is much more complex, but I would be grateful if anyone can tell me whether there are known restrictions on instance variables with dllexport, or if it is more likely that I'm calling a method on a null pointer for Test, or perhaps it is a dllexport and inheritance problem. This code worked before I split the consumer code and DLL code was in the same project, it has only broken since splitting it up, dllexporting/dllimporting functions I want to expose into a second set of headers used by the consumer.
When you pass a Test by value from one place to another in the "consuming code", you'll cause slicing to occur because the client code is unaware of the variable and calculates an incorrect size for the class Test.
To solve this problem, you should declare the variable in the client code as well, or alternatively you can provide a static factory function of some kind and only allow the client code to pass pointers to Tests around to avoid slicing.
If you remove the instance variable from the code supplied to the customer, only your own code knows the real size of your object and can create it. From the top of my head you have two ways to go about this:
Supply a createTest static function that creates an instance of your class (factory method). The nicest thing to do here is to provide a pure interface (no instance variable).
If you only want to hide a specific part of your class you can use the pimpl idiom (wikipedia article).
Is there any reason to not use:
#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif
class fooEXPORT exportClass
{
public:
void function( void );
Foo * var;
}
If you want to hide your class (or part of your class), you could use it as a private member:
#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif
class classToHide;
class fooEXPORT exportClass
{
public:
void function( void );
classToHide * var;
}
And in Cpp:
#include "exportClass.h"
#include "classToHide.h"
void exportClass::function( void )
{
var->function();
}