Conditional compilation

is it possible to express this conditional code construct in swift? i can use #if in other contexts but not like this...

#if useGenericVersion
class MyClass<Type: SomeProtocol> : SomeGenericClass<String, Type.Subtype> {
#else
class MyClass<Ignored>: SomeNonGenericClass {
#endif
    .... something lengthy here
}

now i have to manually comment one of the paths and keep that in sync with "useGenericVersion" variable that is set in project settings:

// useGenericVersion
class MyClass<Type: SomeProtocol> : SomeGenericClass<String, Type.Subtype> {
//class MyClass<Ignored>: SomeNonGenericClass {
    .... something lengthy here
}

i would prefer not to duplicate the class body as it is quite long and except for a few #ifs, the two copies would be identical.

// not ideal:
#if useGenericVersion
class MyClass<Type: SomeProtocol> : SomeGenericClass<String, Type.Subtype> {
    .... something lengthy here
}
#else
class MyClass<Ignored>: SomeNonGenericClass {
    .... something lengthy here and mostly identical to the above
}
#endif

i tried to split it into class + extension with the intention of having two small class bodies and one big extension, but there are way too many restrictions down that road - some things has to be in the class (variables, methods that are overridden in sub classes, etc).

There is not a general solution without using an external preprocessor in today's Swift. There is, however, a mildly awful specific solution:

#if useGenericVersion
typealias MyClassBase<Type: SomeProtocol> = SomeGenericClass<String, Type.Subtype>
#else
typealias MyClassBase<Ignored> = SomeNonGenericClass
#endif

class MyClass<Type: SomeProtocol>: MyClassBase<Type> {
  // …
}
2 Likes

thank you.

i wasn't able using type alias pair for some reason (i didn't investigate fully). however based on your feedback i was able using an intermediate class pair in a similar manner. as an added benefit i created some type aliases in those intermediate classes to further parametrise subclasses' behaviour.

1 Like