Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I specify that a generic is a value type?

I know that we can essentially specify that our generics be any reference type by using AnyObject:

class Foo<T: AnyObject> {
    // ...
}

But is there a way to specify that our generics should only be value types, and not allow reference types?

like image 483
nhgrif Avatar asked Feb 28 '15 13:02

nhgrif


People also ask

How do you identify a generic type?

Use the IsGenericType property to determine whether the type is generic, and use the IsGenericTypeDefinition property to determine whether the type is a generic type definition. Get an array that contains the generic type arguments, using the GetGenericArguments method.

How do you specify a constraint for the type to be used in a generic class?

It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints. You can specify one or more constraints on the generic type using the where clause after the generic type name.

Which types can be used as arguments of a generic type?

The actual type arguments of a generic type are. reference types, wildcards, or. parameterized types (i.e. instantiations of other generic types).

How do you define generic variables?

The generic value variable is a type of variable with a wide range that can store any kind of data, including text, numbers, dates and arrays, and is particular to UiPath Studio. Generic value variables are automatically converted to other types, in order to perform certain actions.


1 Answers

// some code for testing    
class C { } // just a simple class as an example for a reference type
var c = C()
var d: Double = 0.9 // a value type

Solution 1 via extension

protocol ValueType { }
extension Double : ValueType { }
extension Int : ValueType { }
// ... all value types to be added

func printT1 <T: ValueType> (input: T) {
    println("\(input) is value")
}
printT1(d) // Does work
//printT1(c) // Does not work

But as mentioned in the comments, it is working but not feasible, because user defined value types have to implement this protocol.


Solution 2 via method signature

func printT <T: AnyObject> (input: T) {
    println("\(input) is reference")
}

func printT <T: Any> (input: T) {
    println("\(input) is value")
}

Solution 3 via assert

Another solution could be via assert

func printT <T: Any> (input: T) {
    print("\(input) is " + ((T.self is AnyObject) ? "reference" : "value"))
}

"Solution" 4 via where clauses

This would be the best solution, I think. Unfortunately, it is not possible to have

func printT <T: Any where T: ~AnyObject > (input: T) {
    println("\(input) is value")
}

or similar. Maybe it will be possible in future releases of Swift.

like image 99
Michael Dorner Avatar answered Oct 06 '22 16:10

Michael Dorner