more advanced fake covariance

This commit is contained in:
Zahary Karadjov
2017-04-28 18:01:04 +03:00
parent c981284ddc
commit 72f42ff95f

View File

@@ -1,11 +1,56 @@
template accept(x) =
static: assert(compiles(x))
template reject(x) =
static: assert(not compiles(x))
type
BaseObj = object of RootObj
DerivedObj = object of BaseObj
NonDerivedObj = object
Container[T] = object
proc doSomething(c: Container[BaseObj or DerivedObj]) = discard
var base: BaseObj
var derived: DerivedObj
var nonDerived: NonDerivedObj
var t: Container[DerivedObj]
doSomething t
var baseContainer: Container[BaseObj]
var derivedContainer: Container[DerivedObj]
var nonDerivedContainer: Container[NonDerivedObj]
# We can fake covariance by listing some specific derived types that
# will be allowed with our overload. This is not a real covariance,
# because there will be multiple instantiations of the proc, but for
# many purposes, it will suffice:
proc wantsSpecificContainers(c: Container[BaseObj or DerivedObj]) = discard
accept wantsSpecificContainers(baseContainer)
accept wantsSpecificContainers(derivedContainer)
reject wantsSpecificContainers(nonDerivedContainer)
reject wantsSpecificContainers(derived)
# Now, let's make a more general solution able to catch all derived types:
type
DerivedFrom[T] = concept type A
var derived: ref A
var base: ref T = derived
proc wantsDerived(x: DerivedFrom[BaseObj]) = discard
accept wantsDerived(base)
accept wantsDerived(derived)
reject wantsDerived(nonDerived)
reject wantsDerived(baseContainer)
proc wantsDerivedContainer(c: Container[DerivedFrom[BaseObj]]) = discard
accept wantsDerivedContainer(baseContainer)
accept wantsDerivedContainer(derivedContainer)
reject wantsDerivedContainer(nonDerivedContainer)