Apparently, one way to specify a type V, for both field type and supertype parameters, that depends on a constructor boolean value type parameter D, without specifying V in the constructor type parameter, is to:
- Add struct type parameter V to specify that the value types are the same in supertype and field.
- Specify each boolean value in an inner constructor type parameter to constrain its result type.
- Omit the V in each inner constructor type parameter, and specify its value in each
new expression.
struct TestC{D,V} <: AbstractDict{String, V}
d::AbstractDict{String, V}
TestC{true}() = new{true, Union{String, Number}}(Dict{String, Union{String, Number}}())
TestC{false}() = new{false, String}(Dict{String, String}())
TestC(aDict::S) where S <: AbstractDict{String, Union{String, Number}} = new{true, Union{String, Number}}(aDict)
TestC(aDict::S) where S <: AbstractDict{String, String} = new{false, String}(aDict)
end
import Base: iterate, length, get
Base.iterate(t::TestC) = iterate(t.d)
Base.iterate(t::TestC, i::Int64) = iterate(t.d, i)
Base.length(t::TestC) = length(t.d)
Base.get(t::TestC, k::String, dflt) = get(t.d, k, dflt)
import Test: @testset, @test
@testset begin
@test TestC{true, Union{String, Number}} == typeof(TestC{true}())
@test TestC{false, String} == typeof(TestC{false}())
@test TestC{true, Union{String, Number}} == typeof(TestC(Dict{String, Union{String, Number}}()))
@test TestC{false, String} == typeof(TestC(Dict{String, String}()))
@test "TestC{true, Union{Number, String}}(\"one\" => 1)" == string(TestC(Dict{String, Union{String, Number}}("one" => 1)))
@test 1 == TestC(Dict{String, Union{String, Number}}("one" => 1))["one"]
@test TestC{true, Union{String, Number}} <: AbstractDict{String, Union{String, Number}}
@test TestC{false, String} <: AbstractDict{String, String}
@test false == (TestC{true, Union{String, Number}} <: AbstractDict{String, String})
@test false == (TestC{false, String} <: AbstractDict{String, Union{String, Number}})
@test "TestC{true, Union{Number, String}}(\"one\" => 1)" == string(TestC(TestC(Dict{String, Union{String, Number}}("one" => 1))))
@test "TestC{false, String}()" == string(TestC(TestC{false}()))
end
D==trueexpression is always false. Wrapping eachD==trueasprintln_and_return(D)==trueshows that when thestructis evaluated,DisAny. WhenTest{true}(Dict{String, Union{String, Number}}())is called,Dis not evaluated. So the condition expressions in the struct supertype and field type expressions are not evaluated for the constructor expression, and therefore cannot access the constructor type parameter value.