Tuesday 7 November 2017

Abominable Types


As I recently seemingly wasn't able to finish any of the blogpostst I started*, let's have a change of mood and begin with something simple, for example with "abominable types".

What are they? And why did I never hear of them? The answer to the first question is - they are part of C++'s strange menagerie of spooky beasts, of which there are:
  1. nasal demons 
  2. SCARY iterators 
  3. abominable types 
  4. etc... ;-) ** 
Why did I never heard of them? No idea, probably because only compiler writers and template library authors needed to know about them (except from full-time language lawyers of course!). But now, as of appearance of the proposal P0172r0 this language quirk achieved a certain publicity.

1. What they are 

I said I never heard of them, but I know at least why they are called as such - the name seems to originate from Alisdair Meredith:
So what are they again? As stated in P0172r0, this are function type bearing cv or ref qualifiers, for example:
  void foo() const;
  void foo() const volatile;
  void foo() &&;
What? We all know that we cannot define a function with a const qualifier outside of a class, so are these definitions even valid? It seems they are (in a context, more about later). As it is again stated in the told proposal the reason for their mere existence is the desire to enable the following construct:
  struct host {
     int function() const;// { return 42; }
  };

  template <typename TYPE>
  constexpr bool test(TYPE host::*) {
      return is_same_v<TYPE, int() const>;
  }

  constexpr auto member = &host::function;

  static_assert(test(member), "This is why abominations exist");
i.e. checking if some member function is const. As we can see, the problem with abominables is that they aren't function types of member functions but are not types of free functions either! They are halflings, robbed of their context, but coming to life again when provided with such.

By the way, there is a nice, little known trick exploiting the usage shown above (code copied from P0172r0):
  class rectangle {
    public:
      using int_property = int() const;  // common signature for several
methods

      int_property top;
      int_property left;
      int_property bottom;
      int_property right;
      int_property width;
      int_property height;
  };
In the words of the proposal:
"... examples ... explicitly writing these types fall into the category of showing off knowledge of the corners of compilers, and winning obfuscated coding contests."
Facebook's folly::function seems to use it in that manner nonetheless:
  using ConstSignature = ReturnType(Args...) const;

  using NonConstSignature = ReturnType(Args...);

  using OtherSignature = NonConstSignature;

2. The proposal 

Because some (very smart) library writers indeed used the abominables, there was some confusion about the exact goals of the proposal:
So what is the proposal trying to achieve?

The main concern is that when writing generic code we have to consider these function signatures on the overloads, multiplying theitr number by 6. As stated in the proposal:
"In many cases, the simplest option for handling abominable function types in a trait (or other metaprogram) is simply to state that they are not supported. The main problem here is a lack of vocabulary..." 
so you have to fight with them..***. A smaller problem is that they stand out from the type system because they are crippled (remember I called them halflings?)...

OK, I digress. The proposes changes are 1. kill abominable types, 2. make them non-functions, 3. make them regular, 4. minimal library cleanup (along the lines of 2.).

As it seems, 1. was ruled out and 2. is favored. This seems logical, as the abominables are not functions, they are halflings, so they should be demoted to something less than a function - a function-like type!

PS: Maybe there is a newer version of the proposal or a some decision about its fate by now, but as I stated at the start of this post, I just wanted to finish what I started back then.

--
* and I just hit the round number of 100 blogpost drafts... :-/
** look up some of the menagerie here!
** like in c17-features-and-stl-fixes-in-vs-2017-15-3: "std::decay now handles abominable function types (i.e. function types that are cv-qualified and/or ref-qualified)"

Saturday 24 June 2017

QtCreator's debugger broken on Mac???


Problem

As the product of my client is running on both Windows and Mac, we have got our fair share of Mac bugs to be fixed. Yes, we really do, despite the fact that we are using Qt as our cross-platform portability layer! Write once, test everywhere, again... 😞

Unfortunately, we had repeatedly encountered problems with debugging. As we were using QtCreator* on Mac to do Qt-development, we were trying to use its (i.e. QtCreator's) debugger but unfortunately we ran into problems when trying to use breakpoints.

Namely, the debugger seemed to ignore the breaking points we set, as it didn't stop the execution for them! Interestingly, you could step through the code and reach every nook and cranny of it, but you cannot let it run and wait till a breakpoint will be hit. So we had to set our breakpoints directly with LLDB and debug there - no graphical GUI and IDE goodies.

It's needless to say, that this constituted a major obstacle in our quest to eradicate all bugs on Mac. After the annoyance level has hit the high-water mark, my two brave colleagues SaÅ¡a and Bojan came up with a solution which was quite surprising. I just want to share with you, my googling fellow-programmer, and with the rest of internet for the greater good...

Solution

It turned out, that the problem was due to the format of the debug information generated by qmake - it contained relative source file paths, like ../source.cpp. When used directly in LLDB, this didn't pose any problems, everything went well.

Unfortunately, when trying to set a breakpoint out of Qt-Creator, this started to be a issue, as Qt-Creator used full file paths when trying to set a breakpoint with LLDB. You see, file paths didn't match, this just couldn't work! For the sake of completeness it has to be mentioned that QtCreator does not have its own debugger - it just integrates Clang's LLDB and provides an comfortable GUI for it (but you knew it already, I guess...).

The solution was blatantly obvious - one just have to coerce qmake to create debug information containing absolute source file names. This can be done with the
QMAKE_PROJECT_DEPTH=0
option! Done and done!

The only problem is that this isn't an official option but an undocumented one! But it saved the day for us, so we will stay with it for the moment. If you want to read it, there's an interesting article "Undocumented QMake" on the Qt-Wiki. What it says about this special option is:
it seems this represents the number of sub folder that qmake refer to with relative paths (hardcoded is depth=4 in makefile.cpp) ...
As it seems, setting it to zero will force the usage of absolute paths.

Conclusion

As I said earlier, this all is due to SaÅ¡a (and Bojan) so don't give me any credit for that! I'm only the messenger.

As a last word: we are using Qt version 5.6.1 at the moment.

--
* with Clang as compiler and and its LLDB as debugger


Monday 8 May 2017

Qt and "a missing vtable usually means the first non-inline virtual..."


This post is a kind of a "thank you" for a really good piece of advice from a fellow programmer. As it is published on StackOverflow, and I for my part don't use it very much and cannot even upvote it, this post should spread the word about it instead!

Or, alternatively, you can see that post as another installment of an engineering notebook, next one in the series on bug hunting or another piece of advice for the googling programmer*.

The Problem:

I was checking in my changes including promoting a class to a QtObject and everything seemed to be working at first - I tested it locally, it seemed to build in TFS (Team Foundations Server, i.e. in our Windows CI build) but in TeamCity (i.e. in our Mac build) the build was broken with an ominous error message:
NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
And it came from the linker! Initially I supposed some Clang peculiarities (or even bugs) to be held responsible for that, and as I don't have a Mac to check this, I was a little lost for ideads.

The Solution:

But then I found this piece of advice:
Another possibility is that the class in question once didn't belong to Qt meta object system (that is, it had no Q_OBJECT or maybe didn't inherit from QObject at all), so qmake needs to be run again in order to create the necessary rules for MOC. The easiest way to force qmake to be run is to make some insignificant changes to the project file to update its timestamp, like adding and then removing some white space.
As I said, I cannot upvote it (you need at least 15 reputation points for that) so I just say thank you Sergey!

Because... that's exactly it! The missing virtual methods belonged to Qt's signal infrastructure which should be generated by the MOC compiler!

The error didn't manifest itself locally because I generated a Visual Studio project from Qt's .pro files, thus the new MOC file was forced to be created. Thus the problem disappeared trivially.

The same was done in our Windows CI build, but this time only Makefiles were generated and only the "naked" Microsoft compiler was invoked in command line mode to process them. Anyway, the same applies here, MOC creation is forced each time.

On the CI build server however, the "naked" .pro definition files are used, and qmake must be nudged a little to wake up and do its job.

The Moral:

Qmake doesn't like it when we change our minds 😉.

--
* You've got it? Working mathematician etc..? 😊

Friday 24 February 2017

Advanced Stateful Lambdas


Earlier this week I listened to Episode 51 of C++ Weekly Youtube "show" 😉 by @lefticus:
...and I just had to write this cool stuff down before I forget it!

So treat this post as a kind of engineering notebook - not my ideas, not my code, just a remainder and a reference. So without much ado, here's the code:
int main()
{
  auto fib = [a = 0, b = 0] () mutable {
    struct Results {
      int& a;
      int& b;

      Results next(int num = 1) {
        while (num > 0) {
          a = std::exchange(b, b + a);
          --num;
        }
        return *this;
      }
      
      operator int() {
        return a;
      }
    }

    return Results{a, b}.next();
  };

  // main
  return fib().next(5);

  // or:
  // return fib().next().next().next().next().next()

  // or:
  // return fib().next().a;
}
I won't comment on any part of the code, as not to take credit for work of others. If you want to know what this is about, just listen to this episode of C++ Weekly. Or even better, try to find it out by yourself and listen to it after that!

By the way, I support Jason on Patreon, and I think, you should support him too because of his fantastic job with C++ Weekly!

PS: here is another interesting code, this time  from episode 50, exploring generic lambdas and the "template if":
int intTotal = 0;
int doubleTotal = 0.0;
std::common_type<decltype(intTotal), decltype(doubleTotal)> grandTotal;

auto generic_visitor[&intTotal, &doubleTotal, &grandTotal] (const auto v) {
  grandTotal += v;

  if constexpr(std::is_same<double, decltype(v)>{} {
    doubleTotal += v;
  } else {
    intTotal += v;
  }
};