3

I have some code that is multiplying an enum by an integer:

QuantLib::Date date2 = date + 12 * QuantLib::Months;

Where QuantLib::Months is defined as:

enum TimeUnit { Days,
                Weeks,
                Months,
                Years
};

This gives me the desired result of date2 being one year on from date. However, I'm not able to comprehend how this is being achieved.

I had thought that this would not compile. Now I feel that I'm arriving at a "twelve months" object, which the is then handled by the QuantLib::Date '+' operator overload, but I've never seen this style before.

I have come from a C# background, so there may be something I'm not aware of at work here. Can anyone explain what is going on? Any reference documentation would be appreciated.

Chris Spicer
  • 2,144
  • 1
  • 13
  • 22
  • There is nothing strange both in enum implicit conversion and operator overloading. You'd better check all the code involved because Months indeed are converted to 2 and although you may see result date2 was increased for 1 year but the way how it was achieved may contain some surprises – AlexT Feb 25 '14 at 15:07
  • 1
    Don't believe quants - they usually are smart guys but allow dirty tricks. I've just realised that those guys overloaded operator* for enum TimeUnit - nice joke – AlexT Feb 25 '14 at 15:10

3 Answers3

4

One of the following is in effect here:

  1. In C++, an enumeration type can be implicitly converted to an integral type. If this is happening here, date + 12 * QuantLib::Months would be the same as date + 12 * 2.

  2. It is also possible to overload operators for enumeration types. In that case, it might be that the library defines an operator* (int, QuantLib::TimeUnit) which returns something compatible with the + you're doing.

I don't know QuantLib, but I'd guess #2 is what's happening. QuantLib documentation corroborates this (thanks to @DaliborFrivaldsky for the link).

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
1

By default, all enumerations are basically integer constants, and as all integer values you can use them in arithmetic expressions.

In your case the constant QuantLib::Months has the value 2, as enumerations starts from zero and are simply increased.


However, unless you have to make your own data/time functionality, I suggest you use the functionality available in the standard library <chrono> header (or Boost chrono if you don't have a C++11 capable compiler/library). It has all this functionality built-in.

Here is an example similar to your code

auto now = std::chrono::system_clock::now();  // The current time at the moment
auto then = now + std::chrono::hours(24 * 365);

The variable then will now be a time_point 24 * 365 hours in the future from now.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

In your example you are using a so-called unscoped enumeration. Each enumeration has an underlying integral type (that is not necessary the type int There is no such a default rule for enumerations in C++). According to paragraph 4.5.3 of the C++ Standard (you asked some reference to documentation):

3 A prvalue of an unscoped enumeration type whose underlying type is not fixed (7.2) can be converted to a prvalue of the first of the following types that can represent all the values of the enumeration (i.e., the values in the range bmin to bmax as described in 7.2): int, unsigned int, long int, unsigned long int, long long int, or unsigned long long int. If none of the types in that list can represent all the values of the enumeration, a prvalue of an unscoped enumeration type can be converted to a prvalue of the extended integer type with lowest integer conversion rank (4.13) greater than the rank of long long in which all the values of the enumeration can be represented. If there are two such extended types, the signed one is chosen.

So in your example QuantLib::Months is converted to int because all values of the enumeration can be stored in an object of type int. Then usual arithmetic conversions are performed in the multiplicative operation.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335