mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-07 13:33:22 +00:00
79 lines
2.2 KiB
Nim
79 lines
2.2 KiB
Nim
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
|
|
|
|
var base: BaseObj
|
|
var derived: DerivedObj
|
|
var nonDerived: NonDerivedObj
|
|
|
|
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 D
|
|
var derived: ref D
|
|
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)
|
|
|
|
# The previous solutions were solving the problem for a single overload.
|
|
# Let's solve it for multiple overloads by introducing a converter:
|
|
|
|
type
|
|
OtherContainer[T] = object
|
|
|
|
proc wantsBaseContainer1(c: OtherContainer[BaseObj]) = discard
|
|
proc wantsBaseContainer2(c: OtherContainer[BaseObj]) = discard
|
|
|
|
converter derivedToBase(c: OtherContainer[DerivedFrom[BaseObj]]): OtherContainer[BaseObj] = discard
|
|
|
|
block:
|
|
var baseContainer: OtherContainer[BaseObj]
|
|
var derivedContainer: OtherContainer[DerivedObj]
|
|
var nonDerivedContainer: OtherContainer[NonDerivedObj]
|
|
|
|
accept wantsBaseContainer1(derivedContainer)
|
|
reject wantsBaseContainer1(nonDerivedContainer)
|
|
|
|
accept wantsBaseContainer2(derivedContainer)
|
|
reject wantsBaseContainer2(nonDerivedContainer)
|
|
|