# How to use \`@kwdef\` with parametric types and inner constructors

**URL:** https://discourse.julialang.org/t/how-to-use-kwdef-with-parametric-types-and-inner-constructors/107948
**Category:** General Usage
**Created:** [December 22, 2023, 2:27pm UTC](https://discourse.julialang.org/t/how-to-use-kwdef-with-parametric-types-and-inner-constructors/107948 "2023-12-22T14:27:13Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)
#### Post date: [December 22, 2023, 2:27pm UTC](https://discourse.julialang.org/t/how-to-use-kwdef-with-parametric-types-and-inner-constructors/107948/1 "2023-12-22T14:27:13Z")

</div>

I am having problems declaring a parametric structure with `@kwdef` and an inner constructor to perform some checks.

My struct has many parameters and complicated checks, but this simple example is enough to explain my problems:

```julia
@kwdef struct B{T <: Number}
    x::T = zero(T)
    B(x) = begin
        (x < zero(x)) && throw(DomainError("No negative values!"))
        new{typeof(x)}(x)
    end
end

```

This works for all the case of interest but the last one:

```julia
julia> B(0)
B{Int64}(0)

julia> B(0.0)
B{Float64}(0.0)

julia> B(x = 0)
B{Int64}(0)

julia> B(x = 0.0)
B{Float64}(0.0)

julia> B{Int}()
ERROR: MethodError: no method matching B{Int64}(::Int64)

Closest candidates are:
  B{T}(; x) where T<:Number
   @ Main util.jl:579

Stacktrace:
 [1] B{Int64}(; x::Int64)
   @ Main ./util.jl:579
 [2] B{Int64}()
   @ Main ./util.jl:579
 [3] top-level scope
   @ REPL[50]:1

```

I tried to explore what `@kwdef` is doing using `@macroexpand`, but I find nothing strange: in the definition of `B` I see one inner constructor (the one I defined) and two outer constructors defined by `@kwdef`, including `B{T}(; x = zero(T)) where T <: Number`: I cannot understand why this is not called by `B{Int}()`.

May somebody explain me why `B{Int}()` is incorrect, please? What would be the best way to construct `B` without specifying any parameter but the type `T`?

---

<div class="post-metadata">

### Author: ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)
#### Post date: [December 22, 2023, 5:08pm UTC](https://discourse.julialang.org/t/how-to-use-kwdef-with-parametric-types-and-inner-constructors/107948/2 "2023-12-22T17:08:53Z")

</div>

Your inner construct needs to be parameteric too:

```julia
@kwdef struct B{T <: Number}
    x::T = zero(T)
    B{T}(x::T) where T = begin
        (x < zero(x)) && throw(DomainError("No negative values!"))
        new{T}(x)
    end
end

```

The reason is that when you define an inner constructor, you ‘delete’ all other default inner ones too, which includes `B{T}(x::T)`. But the latter is required by one of the outer constructors that is generated with `@kwdef` (from `@macroexpand @kwdef ...`)

```julia
 (B{T}(; x = zero(T)) where T <: Number) = begin
                #= util.jl:579 =#
                B{T}(x)
            end

```

---

<div class="post-metadata">

### Author: ![Maurizio\_Tomasi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/maurizio_tomasi/32/384_2.png) [@Maurizio\_Tomasi](https://discourse.julialang.org/u/Maurizio_Tomasi)
#### Post date: [December 22, 2023, 5:30pm UTC](https://discourse.julialang.org/t/how-to-use-kwdef-with-parametric-types-and-inner-constructors/107948/3 "2023-12-22T17:30:38Z")

</div>

Oh, I see. I was under the wrong impression that Julia was missing the presence of the outer constructor. Thanks a lot!
