What's this ellipsis in c++ : #define MBGL_DEFINE_ENUM(T, values...)? - c++

While trying to build mapboxgl-native with msvc 2017, I had errors with the following construct in their enum.hpp
#define MBGL_DEFINE_ENUM(T, values...)
This macro is used like this
I could not find the documentation for this c++ syntax.
Which version of c++ defines this ellipsis construct ? How is it called ?

This isn't standard C++. The standard way would not name the ellipsis. It's a GCC extension.
Variadic macros in standard C++ look somewhat like this:
#define foo(arg, ...) arg __VA_ARGS__
Where __VA_ARGS__ stands for all the arguments in the ellipsis.

Related

Is Q_PROPERTY a function-like macro in C++?

In my opinion,the using of a function-like macro in C++ is similar to the using of a common function. It seems to be like this:
macroFunctionName(arg1, arg2, arg3);
However, the using of Q_PROPERTY usually looks like this:
Q_PROPERTY(Qt::WindowModality windowModality READ windowModality WRITE setWindowModality)
As we can see, they are different.There is no comma in the using of Q_PROPERTY.I have never seen a function-like macro which was used like Q_PROPERTY.I am even not sure whether Q_PROPERTY is a function-like macro in C++.So is it ill-formed in C++? Or it's just a special syntax for MOC in Qt?
I tried to find it in the C++ standard document but nothing about it was found.
I looked in Qt's ./src/corelib/kernel/qobjectdefs.h file for the definition, and it looks like this:
#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
... which would make Q_PROPERTY a variadic macro. Of course all it does is expand out to QT_ANNOTATE_CLASS, which is a different macro, one that Qt's moc utility presumably knows how to handle in a meaningful way when generating its moc_*.cpp files.
As for the use of spaces rather than commas; you're right, the preprocessor doesn't treat spaces as argument-separators. I suspect that the C++ preprocessor is simply passing the entire line (i.e. "Qt::WindowModality windowModality READ windowModality WRITE setWindowModality") into the QT_ANNOTATE_CLASS macro as a single argument, and that moc's QT_ANNOTATE_CLASS macro-definition is doing some stringification preprocessor tricks in order to parse it as a string-argument.

Is variadic macro expansion possible in GLSL?

In C99 we have variadic macro expansion via the #define XXX(...) __VA_ARGS__ syntax.
This doesn't seem to work in GLSL.
Is there a similar mechanism with different syntax? Is this implementation specific?
The GLSL specification borrows most of its preprocessor behavior from C++. Specifically, C++98. As such, it does not have variadic macros. Nor does it have anything like them.

Macro for generalized lambda capture

I would like to use the generalized lambda capture introduced in C++14 (see Move capture in lambda for an explanation). However, the remainder of my code is C++11-friendly. I would like to do something along the lines of
#ifdef CPP14
// move capture in lambda
#else
// capture by-value
#endif
However, there are no good cross-compiler flags to infer versions. Is there anything anyone can suggest? (other than, of course, defining my own macros)
Actually T.C. is right, the C++11 FDIS says in "16.8 Predefined macro names [cpp.predefined]" that
The name __cplusplus is defined to the value 201103L when compiling a C++ translation unit.
The footnote states:
It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming com- pilers should use a value with at most five decimal digits.
So going with the following code seems totally legit to me.
#if __cplusplus > 201103L
//c++1y or above
#else
//c++11 or below
#endif
However, some compiler might not follow the standard and you might want to check if the _cplusplus value has been incremented for c++1y.
The GCC, for example, had this flag set to 1 until the version 4.7.0.
If you need more information on the _cplusplus flag, you should take a look at this question

#ifdef inside a macro call works with gcc but not with msvc [duplicate]

This question already has an answer here:
Are preprocessor directives allowed in a function-like macro's argument?
(1 answer)
Closed 5 months ago.
I am have a macro TYPELIST which takes variadic arguments. I want to have something like
typedef TYPELIST(A
,B
,C
,D
#ifdef BLA_
,E
#endif
,F)
This works perfectly with gcc. However, when I try to compile it with MSVC it parses ifdef and endif as macro arguments. I know one way would be to put the macro call inside an ifdef. However, if I have a huge list and if I want to include different classes depending on different macros defined, it would become tedious. Is there a particular reason why this works in gcc and not with MSVC?
Using #ifdef inside a macro isn't legal. I am sort of surprised that gcc allows this. I'm afraid you have to put the #ifdef around the entire definition, i.e.
#ifdef BLA_
typedef TYPELIST(a,b,c,d,e,f)
#else
typedef TYPELIST(a,b,c,d,f)
#endif
According to the standard (ยง16.3.4/3), "The resulting completely
macro-replaced preprocessing token sequence is not processed as
a preprocessing directive even if it resembles one,[...]". If
g++ processes the #ifdef/#endif here, it's an error in the
compiler (at least if you've requested standards conformance,
e.g. with -std=...).

Is this macro statement legal C++ or something else? And if it is legal how does it work

WebKit has a lot of pre-processor lines like this:
#if MACRO1(MACRO2)
For example:
#if PLATFORM(MAC) || (PLATFORM(QT) && USE(QTKIT))
#include "MediaPlayerPrivateQTKit.h"
#if USE(AVFOUNDATION)
#include "MediaPlayerPrivateAVFoundationObjC.h"
#endif
...
So my first thought was that they were function-like macros, but I can't see how that would work, and I couldn't find any #defines for these macros anywhere in the source code.
I asked another engineer what it was and he's never seen multiple macros used like that inside a #if before either.
I found this wiki page that talks about them but it still wasn't clear to me where they come from,
So my question then: Is this valid C++ or is it being replaced in the code by another tool/language like CMake or something else, and if it is valid C++ is there a spec anyone is aware of that talks about this?
I'm a support engineer for a C++ Static Analysis tool that isn't handling this syntax. A customer asked us to handle it, but if I'm going to take this to the senior engineer I'd like to not sound like an idiot :) So I'd like the nitty gritty if anyone knows it.
As mentioned in the wiki, in root/trunk/Source/JavaScriptCore/wtf/Platform.h we get a definition for each of these defines. For instance, the PLATFORM macro is defined as:
#define PLATFORM(WTF_FEATURE) \
(defined WTF_PLATFORM_##WTF_FEATURE \
&& WTF_PLATFORM_##WTF_FEATURE)
The value of WTF_FEATURE will be replaced by the platform name to create some macro named WTF_PLATFORM_WTF_FEATRE. For instance, with WTF_FEATURE passed into the macro as MAC, you would end up with a expansion of WTF_PLATFORM_MAC. The pre-processor defined directive combined with the logical AND is basically asking whether that macro value defined, and if it is defined, if its value is a "true" value. You would use this macro somewhere else in the pre-processor like:
#ifdef __APPLE__
#define WTF_PLATFORM_MAC 1
#end if
#define PLATFORM(WTF_FEATURE) \
(defined WTF_PLATFORM_##WTF_FEATURE \
&& WTF_PLATFORM_##WTF_FEATURE)
#if PLATFORM(MAC)
//...some code
#end if
You wouldn't use it within C++ code itself like
if (PLATFORM(MAC))
{
//...some code
}
that would cause a bunch of errors from the compiler since defined is not a C++ keyword, and the evaluation and replacement of the macro within C++ code would end up dumping the defined pre-processor directive into any C++ code that directly called the macro. That's not valid C++.
Thanks you to Johannes for pointing out some of these issues.
The #if directive roughly works by replacing all macros, and then replacing all identifier and keywords of what's left by 0 and afterwards processing what's left has a constant expression according to the rules of the C++ language (the subset of those rules applicable to what's left from that replacing - quite little :)).
So PLATFORM(MAC) may yield a 1 if MAC is defined to be 1, and a MAC if it is not defined, if PLATFORM is simply defined as
#define PLATFORM(X) X
The resulting MAC is an identifier and will later be replaced by 0. It's more likely that they are concatenating the X to something like PLATFORM, so as to support multiple queries with MAC as argument, testing for existence of different macros. As a developer of a " C++ Static Analysis" tool you probably have access to the C++ spec. Take a look at clause 16.1.
The definitions may be coming from the build scripts. Most C++ compilers let you define macros on the command line.
One way I can see to define a USE macro like in your example would be:
#define USE_QTKIT 1
#define USE(x) USE_ ## x
Or maybe like:
gcc -DUSE_QTKIT=1 '-DUSE(x)=USE_ ## x'