Macros in the Middle of a Class or Function Declaration

Macros in the middle of a class or function declaration

I've learnt from here and here that macros like that above are used to tell the linker how to link it properly, or something like that.

To be pedantic, it's not the macro that tells the linker how to link. The macro is simply replaced by the preprocessor by whatever text it's defined to be replaced with. In the case of your example, it would be conditionally replaced with __declspec(dllexport) or __declspec(dllimport). Those declspec specifiers on the other hand do tell the linker what to do... at least some linker that understands the specifier.

since when was it legal to just put something like __declspec(dllimport) in the middle of a class declaration anyway?

Since Microsoft implemented their compiler and specified that it's legal. It's not legal according to the c++ standard.

In which part of the C++ standard does it say that class declarations like this are legal?

It doesn't. Using those specifiers is non-standard and not guaranteed to work in any other compiler than Microsoft's. That's why such macro is typically defined to expand to an empty string (or possibly something else, specific to another implementation) when used in a compiler that does not support the keyword.

What actual thing is __declspec(dllimport)?

It is a non-standard keyword. You can find out more from their (Microsoft) documentation.

To dive a little bit deeper, the keywords tell the linker how to export symbols when compiling a shared (dynamically linked) library. Dynamic linking is a concept that's entirely foreign to the standard. It's implementation defined.

how I might go about using this kind of declaration myself, in a program that I might write from scratch, myself.

Do you intend to write a shared library? If not, then you don't need to know. If yes, then you need to read the documentation of every platform that you're targetting.

Here is a walkthrough in the Microsoft's documentation that guides you through the steps to create a dynamically linked library.

What's a macro before a function or a class in C++?

Usually such things are a placeholder for compiler or system specific extensions to the language.

For example, if building a program using a windows DLL, to import a symbol the function might be declared

__declspec(dllimport) void foo();

The problem is that the __declspec(dllimport) would typically not work if the code is ported to another system, or built using a compiler that does not support such a non-standard feature.

So, instead, the declaration might be

#ifdef _WIN32    /*  or some macros specific to a compiler targeting windows */

#define IMPORT __declspec(dllimport)
#else
#define IMPORT
#endif

IMPORT void foo();

There are a number of occasions, with particular compilers, targets (e.g. a program importing a symbol from a library, or a library being built to export a symbol), and host systems where such a technique might be used.

C++ method declaration including a macro

It means that the class is either exported or imported, depending on which module is built.

If QUICKFAST_HAS_DLL is defined and equal to 1, it means that the module is built as a DLL. To use functionalities from the outside, classes and methods have to be exported.

Inside the module, QUICKFAST_BUILD_DLL is defined. So when you build the module, QuickFAST_Export expands to __declspec(dllexport). Your class definition becomes:

class __declspec(dllexport) Message : public FieldSet

When you include the header from a different module, QUICKFAST_BUILD_DLL is not defined, so the macro expands to __declspec(dllimport), and your class definition to:

class __declspec(dllimport) Message : public FieldSet

What's a macro before a function or a class in C++?

Usually such things are a placeholder for compiler or system specific extensions to the language.

For example, if building a program using a windows DLL, to import a symbol the function might be declared

__declspec(dllimport) void foo();

The problem is that the __declspec(dllimport) would typically not work if the code is ported to another system, or built using a compiler that does not support such a non-standard feature.

So, instead, the declaration might be

#ifdef _WIN32    /*  or some macros specific to a compiler targeting windows */

#define IMPORT __declspec(dllimport)
#else
#define IMPORT
#endif

IMPORT void foo();

There are a number of occasions, with particular compilers, targets (e.g. a program importing a symbol from a library, or a library being built to export a symbol), and host systems where such a technique might be used.

C++ - Two names in class declaration (macros)

Usually when you see OMGWFT_API declarations in this exact way, this is a 'magic switch' for building a library in correct "mode":

  • static linking - OMGWFT_API replaced by "" (empty string)
  • dynamic linking - DLL - OMGWFT_API replaced by declspec(dllexport)
  • dynamic linking - EXE - OMGWFT_API replaced by declspec(dllimport)

i.e.

#ifdef BUILD_ME_AS_STATICLIB
#define OMGWFT_API
#else
#ifdef BUILD_ME_AS_DLL
#define OMGWFT_API declspec(dllexport)
#else
#define OMGWFT_API declspec(dllimport)
#endif
#endif

This is of course just an sketch of example, but I think you get the point now. Keywords are taken from MSVC not GCC< because I accidentially happen to remember them.

The "BUILD_ME_AS...." macros would be then defined via project options or -D command line switch.

However, it the OMGWFT_API can be set to have any meaning, so be sure to grep/search for a #define that sets this.

How to pass a class function (ClassName::function) reference in c++ MACRO

You are passing a non static member function pointer, which requires a class instance to call. If you change that to a static member or a free function, it should work OK.

class A{
...
static bool square(...);
};

TEST(A::square,...);

or

bool square(...);

TEST(square,...);

Also your macro has a typo - func_ptr vs funct_ptr

Is it possible to use #define inside a function?

#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:

for(int i = 0; i < 54; i++) {
#define BUFFER_SIZE 1024
}

is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.

You can write #define everywhere since the preprocessor is not really aware of the program itself.

Preprocessor directive in middle of c++ function?

When does the #ifdef execute in the above function?

It is executed before "the compiler" sees the code. If the preprocessor knows what the TOOLS_ENABLED symbol is, then the preprocessor continues to pass this code to the compiler.

If the preprocessor does not know what TOOLS_ENABLED is, then it will skip this chunk of code, and not pass that code to the compiler.

Its a common trick, usually to allow "debug" builds to do a bunch of additional validation to affirm that no bug has occured, but to eliminate all this slow doublechecking from "release" builds so that they run super fast.

Macro errors with member function

The function pointers aren't equivalent.

void (*type_name_t)(Test*)

is not the same as

&Test::type_name

Your function pointer is of type: a pointer to a function that takes one argument, a Test pointer, and returns no value.

What you want is a pointer-to-member-function, specifically, a pointer to a member function that takes no arguments and returns no value:

void (Test::*type_name_t) (); // note the empty parameter list!

Preprocessor macro overriding function definition in c++

In your compiler settings, have NOMINMAX be defined. This will stop the Windows headers from trying to define the min and max macros. This is the correct way to handle this issue; trying to #undef it is unreliable and error-prone. Search for NOMINMAX for more information on this flag.

You can also do this in a pinch, but don't make it a habit:

SUMOReal distance = (std::numeric_limits<SUMOReal>::max)();


Related Topics



Leave a reply



Submit