Dealing with "override" and "final" keywords


#1

C++11 has introduced ‘override’ and ‘final’ keywords.

Due to the potential difference in (lack of) support of those two keywords by various compilers, what do you think about #defining them for those compilers that don’t support them, the same way it has been done for ‘nullptr’ and ‘noexcept’

I think that #definining them to an empty string will be just fine. here are some hints: http://stackoverflow.com/questions/7419472/qtcreator-how-do-i-register-override-and-final-as-a-keyword


#2

Yes, I’m very keen to start using those, and will do the same trick I did nullptr. (I’m already using them in some of my non-public projects)

If I had time to investigate, there’s a new clang c++11 migration tool that can automatically add them to your code where appropriate. That’d be the smart way to do this, as there are probably many thousands of places where override could usefully be added.


#3

I agree with that, I was just asking if you could add the #define for the keyword in the juce header so that who wants to use them can safely do that even on compilers that don’t support them (and so they will be ignored)


#4

Yep, will add that soon!


#5

The define in the current code just break all the compiler we are using.

“final” is used in OpenSSL as a method name, so as soon as you define it to nothing, it breaks.
On the other side, none of our compiler are “override” capable, so I must define the workaround preprocessor macro to get “override” defined out, and it also breaks.

As a result, the current version of Juce does not build anymore.


#6

The idea with my override definition was that it should detect whether the compiler supports it - let me know which compiler you’re using and I’ll correct that…


#7

The one in Visual studio 2010, and gcc 4.6 (in debian squeeze), gcc 4.7 (in Wheezy), a cross compiler gcc 4.4 for ARM, clang++ 4.0 on a Mac (this one works).
I don’t think detecting the compiler is a good idea anyway.

Can you split OVERRIDE and FINAL macro, so we can fit out what work and what not on our side ?
When not using openssl, I can use the macro to void the keywords, but as soon as I’m using a C library that’s using the C++ keyword, then macro magic breaks the include’d code.

So, a good solution would be you use “jfinal” and “joverride” (and not “final” and “override”) and #define jfinal final when the compiler supports it (or when the user does not disable it), and ditto for override.


#8

huh? That makes no sense - I use all those compilers myself, and everything works correctly AFAICT.

Re: final, that’s deeply annoying about openSSL - what I’ll do is just remove that #define from the code, as I don’t actually use final yet anyway. At some point in the future maybe I’ll add it back somehow.

But no, I don’t agree that joverride would be a good move - I want the code to be real C++11 if possible, and the same trick has worked well for a long time with nullptr.


#9
$ gcc -v
[...]
gcc version: 4.4.5
$ make
[...]
ListBox.cpp(36): error: expected ';' before 'override' 

I think no one would call a function “nullptr”, and even if someone did, it would have broken the build too.

I see your point through, as soon as a new keyword is used, it’ll break with C libraries using that “legitimate” keyword for whatever other reason.
Anyway, since it’s just a matter of time until the OpenSSL developers, tired of C++ user complaints, change their method name, I would expect you transition slowly, and not abruptly.

So, back to the former request, can you split override & final macro magic in 2 different part ?
That way, I could do on my side:

// Whatever previous macro state

#include "openssl" // Can't be done currently, as it breaks juce's code, as to be after juce's header declaration. 

#define final jfinal
#define override joverride
#include "juce code"
#undef final
#undef override

#10

Something in your code must be affecting this. The code contains this line:

#if (! JUCE_CLANG) && defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 40700 #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 #endif

…so for gcc4.4 it should know that the compiler doesn’t support it, and will #define override to do nothing. If you’re not seeing that, then I’ve no idea why the code above would fail (?)

Like I said, I’ll actually remove “final” altogether to avoid your openssl problem… Can’t really see a need to change the way it handles override though.


#11

Mine gives:

$ cat a.c
#include <stdio.h>

int main()
{
  printf("%d %d\n", __GNUC__, __GNUC_MINOR__);
return 0;
}

$ ./a.out
4 4

So basically, (4 * 100 + 4) is not >= 40700.
Tried on a 4.7, it’s 407, and again, not 40700, and ditto for 4.8 too.
So this test will never kick in.

Anyway, I need this macro to be set: JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL, so it does not “void” final and override, I’m defining it manually.
BUT, and that’s the point, override is not supported by the compiler, so it breaks compilation on it. If I don’t define the macro, it prevents compiling OpenSSL code header.

Please change to this:

//==============================================================================
// Here, we'll check for C++11 compiler support, and if it's not available, define
// a few workarounds, so that we can still use some of the newer language features.
#if defined (__GXX_EXPERIMENTAL_CXX0X__) && defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
 #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1
 #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
 #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
#endif

#if JUCE_CLANG && defined (__has_feature)
 #if __has_feature (cxx_nullptr)
  #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
 #endif

 #if __has_feature (cxx_noexcept)
  #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1
 #endif

 #if __has_feature (cxx_rvalue_references)
  #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
 #endif

 #ifndef JUCE_COMPILER_SUPPORTS_OVERRIDE
  #define JUCE_COMPILER_SUPPORTS_OVERRIDE 1
 #endif

 #ifndef JUCE_COMPILER_SUPPORTS_FINAL
  #define JUCE_COMPILER_SUPPORTS_FINAL 1
 #endif


 #ifndef JUCE_COMPILER_SUPPORTS_ARC
  #define JUCE_COMPILER_SUPPORTS_ARC 1
 #endif
#endif

#if defined (_MSC_VER) && _MSC_VER >= 1600
 #define JUCE_COMPILER_SUPPORTS_NULLPTR 1
 #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1
#endif

#if defined (_MSC_VER) && _MSC_VER >= 1700
 #if !defined(JUCE_COMPILER_SUPPORTS_OVERRIDE)
   #define JUCE_COMPILER_SUPPORTS_OVERRIDE 1
 #endif
 #if !defined(JUCE_COMPILER_SUPPORTS_FINAL)
   #define JUCE_COMPILER_SUPPORTS_FINAL 1
 #endif
#endif

#if (! JUCE_CLANG) && defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
 #if !defined(JUCE_COMPILER_SUPPORTS_OVERRIDE)
   #define JUCE_COMPILER_SUPPORTS_OVERRIDE 1
 #endif
 #if !defined(JUCE_COMPILER_SUPPORTS_FINAL)
   #define JUCE_COMPILER_SUPPORTS_FINAL 1
 #endif
#endif

//==============================================================================
// Declare some fake versions of nullptr and noexcept, for older compilers:
#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NOEXCEPT)
 #ifdef noexcept
  #undef noexcept
 #endif
 #define noexcept  throw()
 #if defined (_MSC_VER) && _MSC_VER > 1600
  #define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining)
 #endif
#endif

#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NULLPTR)
 #ifdef nullptr
  #undef nullptr
 #endif
 #define nullptr (0)
#endif

#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_OVERRIDE)
 #undef  override
 #define override
#endif
#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_FINAL)
 #undef  final
 #define final
#endif

#12

g++ supports override only when c+±11 support is enabled , AFAIK. In my code the test to enable override is: #if __cplusplus >= 201103L