Parametric type specialization (like C++ template specialization)

Is there some way to express the following, which is like a C++ template specialization?

Let’s define a parametric type:

struct MyType{N<:Integer}
  field::GenericType
end

In the special case where N==1, we can do better:

struct MyType{N==1}
  field::SpecificType
end
2 Likes

You could do it via a constructor, e.g.,

struct MyType{T}
    field::T
end
function MyType(N::Integer)
    if N == 1
        MyType{SpecificType}(value)
    else
        MyType{GenericType}(value)
    end
end

It would be type unstable at the point of construction but that’s often not too much of an issue so long as it’s not in the middle of a speed critical loop. Using a function barrier (or simply the constant propagation optimisations) would get you back up to full speed.

2 Likes

No this is not possible, but there are various alternatives. I guess the most common options are

struct MyType{N,T}
    field::T
end

or

abstract type MyType{N} end
struct MyGeneric{N} <: MyType{N}
    field::Generic
end
struct MySpecial <: MyType{1}
    field::Special
end
5 Likes

Thanks for this suggestion. Indeed the result should be good, but it loses a lot in expression I believe. It is much neater if it can be sorted out at compile-time.

Yes, it probably is reasonable to leave the type as a parameter and wrap it with another type that chooses the specific field type.

My use case is to make a type with a specific API and build my logic around it, while retaining flexibility as to how this type implements its operations internally. For some specific instances of this parametric type I currently have an efficient implementation, whereas for others I don’t. In all cases, I want to be able to plug in a more efficient implementation in the future.

FWIW if N is a constant then the constant propagation optimizations within the compiler mean that it should be sorted out at compile time.

If you absolutely want it to be done at compile time then check out value types but note that the constant propagation optimisations largely achieve the same effect.

If N isn’t a constant then it can’t be sorted out at compile time anyway :slight_smile:

1 Like

Instead, you could just build your API around a collection of methods rather than a specific type. That would allow you to create as many specialized implementarions as you want, and also would allow others people to create their own implementarions in the future.

4 Likes

Basically what @jw3126 is suggesting. I think this is what I’ll do, I’ll build my API on an abstract type and then make distinct specializations of it. Now that I think of it better, this is exactly the meaning I want to give, only expressed a bit differently. I was thinking in terms of C++ template specialization, but in the end it is very close to jw3126’s 2nd suggestion.

2 Likes