1

There's a class template that I would like to deprecate in my project.

template<typename T, size_t Size>
class X {};

I've come up with a following scheme to do that.

Stage 1

For next release - let's say version "5" - I'm going to provide the "new" class with different name (the replacement) and convert the old one to a deprecated alias:

template<size_t ElementSize, size_t Size>
class X2 {};

template<typename T, size_t Size>
using X __attribute__ ((deprecated)) = X2<sizeof(T), Size>;

This will cause a warning for all users of the "old" API, but the code will still work.

Stage 2

In the next version - "6" - I'm going to remove the "old" deprecated class, rename the "new" one to the old name and create a deprecated alias:

template<size_t ElementSize, size_t Size>
class X {};

template<size_t ElementSize, size_t Size>
using X2 __attribute__ ((deprecated)) = X<ElementSize, Size>;

This will again cause the warning for the users.

Stage 3

In this final step - done in version "7" - I'll remove the deprecated alias, leaving only the changed class.

template<size_t ElementSize, size_t Size>
class X {};

This whole scheme has some pros (at each stage the code compiles and works, only warning is issued for deprecated interface) and cons (the users are forced to change their code twice). However I did not come up with anything better - all other options I considered involve a compilation error at some point. The main problem I'm facing here is that I would like to keep the name of the class (in the final stage), but change the template "signature" from <type, value> to <value, value>, which (as I assume) precludes all other clever options...

Is there any better option? If not, does the above scheme seem "acceptable", or maybe I should just cause one single compilation failure and be done with that? The project is in an early stage of development, so I'm not very much concerned about backward compatibility, but I thought this is a very good opportunity to try out the whole process.

Freddie Chopin
  • 8,440
  • 2
  • 28
  • 58
  • 3
    I'm not sure this has much to do with templates (or indeed, classes!). This is the generic global problem of "how do I introduce backward-incompatible changes?". – Oliver Charlesworth Apr 07 '17 at 13:26
  • A gradual deprecation and removal over multiple releases are usually a good way to go. This might be easier if using something like [semantic versioning](http://semver.org/) of the product. Also, *documentation documentation documentation* is oh so important for this. – Some programmer dude Apr 07 '17 at 13:26
  • @OliverCharlesworth - the problem would be easier in case of function depreciation, because I would introduce an overload and be done with it, but here it's not possible to have a "template overload" which changes "type" to "value" in the signature... – Freddie Chopin Apr 07 '17 at 13:36

1 Answers1

1

An easier solution might be to introduce a pair of macro's.

In phase 1, code which defines USE_NEW_API can already use the new API. In phase 2, code which defines USE_OLD_API can still use the old API. In phase 3, the macro's are ignored and all code must use the new API.

Of course, mixing the old and new API in one program is slightly more troublesome, and mixing them in one Translation Unit is begging for problems.

Behind the scenes, in phase 1 you have a #if !(defined(USE_OLD_API) || defined(USE_NEW_API)) #define USE_OLD_API which you switch over to #define USE_NEW_API in phase 2.

MSalters
  • 173,980
  • 10
  • 155
  • 350