I use operator* to deference a pointer inside my C++/CLI class and the compiler gives a warning about this operation:
C4383: 'instance_dereference_operator' : the meaning of dereferencing a handle can change, when a user-defined 'operator' operator exists; write the operator as a static function to be explicit about the operand
How can I avoid this warning? This is the code:
ref struct MyClass
{
// ...
T& operator*()
{
return *m_pValue;
}
// ...
}
Finally I implemented as static operator overload as #hans-passant suggests:
static T& operator*(MyClass %obj)
{
return *obj.GetActualValue();
}
Related
Trying to convert some Java code to Kotlin, the Java code includes a call to a library method TableUtils.dropTable which is implemented in Java. The Java method signature of this method is
public static <T, ID> int dropTable(ConnectionSource connectionSource, Class<T> dataClass, boolean ignoreErrors) throws SQLException
When calling the method from Java it compiles fine even though the type variable ID is not known. For example:
public void method(ConnectionSource connectionSource, Class<? extends IRecordObject> clazz) {
try {
TableUtils.dropTable(connectionSource, clazz, true); // this compiles fine
} catch (SQLException e) {
e.printStackTrace();
}
}
After converting to Kotlin, the corresponding function fails to compile because the type variable ID cannot be inferred:
fun method(connectionSource: ConnectionSource?, clazz: Class<out IRecordObject>) {
try {
TableUtils.dropTable(connectionSource, clazz, true) // compile error: "Not enough information to infer type variable ID"
} catch (e: SQLException) {
e.printStackTrace()
}
}
I don't know how I can explicitly specify the type variables, as one of them would be a wildcard, and you aren't allowed to use wildcards in type variables when calling functions. For example:
TableUtils.dropTable<out IRecordObject,Long>(connectionSource, clazz, true) // this also fails to compile, "Projections are not allowed on type arguments of functions and properties"
So how can I specify the type variable ID here to allow the code to compile in Kotlin?
The type ID is unused in the function signature, so it doesn't matter what it is. For the Kotlin version, you can literally put any type there to make the error go away. Whichever type you use will have no effect on the compiled code because of type erasure. You can use an underscore to allow T to be inferred.
fun method(connectionSource: ConnectionSource?, clazz: Class<out IRecordObject>) {
try {
TableUtils.dropTable<_, Unit>(connectionSource, clazz, true)
} catch (e: SQLException) {
e.printStackTrace()
}
}
I actually don't know how you can write out the type and make it work instead of using inference. The only way I can think to make it work is to make this function generic so you can use an invariant Class type:
fun <T: IRecordObject> method(clazz: Class<T>) {
JavaFoo.dropTable<T, Unit>(clazz, true)
}
I think the Java method signature should have used Class<? extends T> for more proper flexibility and probably should have omitted ID since it is effectively useless.
fun handle() : String {
null?.let { return "Ololo"}
}
val result = handle()
result.trim() // kotlin.TypeCastException: null cannot be cast to non-null type kotlin.CharSequence
Any ideas why null-safe Kotlin function return null?
It's a bug caused by introducing contracts for the standard functions let, run, apply, also in Kotlin 1.3.
The fix is targeted to the version 1.3.20. See KT-28061 for details.
It looks like the Kotlin compiler is adding in a null return in case let doesn't execute. This is probably a bug, since it shouldn't compile, and doesn't in previous versions of Kotlin.
If we just compile your example, we get this:
#NotNull
public final String handle() {
return null;
}
I think that's just a compiler optimization, since null?.let() will never execute.
Using an actual variable yields:
#NotNull
public final String handle() {
return someNullableVariable != null ? "Ololo" : null;
}
In other words, let() doesn't execute if its reference is null. However, since this function needs to return something, the compiler just tells it to return null, since there's nothing else it could return.
Since the function is marked #NotNull, Kotlin will perform a null-check on anything referencing the function:
fun someOtherMethod() {
handle().trim()
}
Becomes
public final void someOtherMethod() {
String handle = handle();
if (handle != null) {
StringsKt__StringsKt.trim(handle).toString();
return;
}
throw new Exception("null cannot be cast to non-null type kotlin.CharSequence");
}
There are two ways to handle this. You could change the return type on handle() to String?:
fun handle(): String? {
someNullableVariable?.let { return "Ololo" }
}
Or you could return something else in case the variable is null:
fun handle(): String {
someNullableVariable?.let { return "Ololo" }
return "someNullableVariable was null"
}
It has to be a bug, because:
a return statement (or better: expression) is missing, since the lambda passed to let won't be invoked
a function with String as return type should never return null.
Interestingly, in Kotlin 1.2.x this does not even compile:
fun handle() : String {
null?.let { return "Ololo"}
}
Error:(6, 0) A 'return' expression required in a function with a block body ('{...}')
In Kotlin 1.3.11 it does.
In any case:
let won't be invoked, because the safe-call operator ? evaluates to null (in this case).
I want to wrap a c++ pointer field to property in CLI, here is my code:
class NativeClass
{
public:
int* nativeApointer;
}
ref class ManagedClass
{
NativeClass* thisClass
property int^ A
{
int^ get()
{
return thisClass->nativeApointer
}
}
}
compiler noticed errror, so how did convert unmanaged pointer to interior pointer?
I thought that in Kotlin, Unit was equivalent to Void. With Vert.x Service Discovery, it is not possible to pass a Future<Unit> to unpublish(String id, Handler<AsyncResult<Void>> resultHandler) (gives a type mismatch) yet it will accept Future<Void> without any problem. Why is this and is there a solution or will I just have to live with using Void?
Unit is not equivalent to Void, it is equivalent to void in kotlin.
In java, void is a keyword, but Void is a class. so the code below can't be compiled:
fun foo():Void{/**need return a Void instance exactly**/}
fun bar():Void{ return Unit; }
// ^--- type mismatch error
java applies the same rule, for example:
Void canNotBeCompiled(){
// must return a Void instance exactly.
}
Void foo(){
return Void.TYPE;
}
Void nil(){
return null;
}
Finally the Unit documentation also says:
The type with only one value: the Unit object. This type corresponds to the void type in Java.
I have a delegate method that passes an enum as an argument:
func gestureRecognizer(gestureRecognizer: JTTableViewGestureRecognizer!, commitEditingState state: JTTableViewCellEditingState, forRowAtIndexPath indexPath: NSIndexPath!) -> Void {
//....
}
The enum is JTTableViewCellEditingState. It's implementation is in the same header file as the delegate method. It's as follows:
typedef enum {
JTTableViewCellEditingStateMiddle,
JTTableViewCellEditingStateLeft,
JTTableViewCellEditingStateRight,
} JTTableViewCellEditingState;
Yet trying to reference a state, for example Left, gives an error:
if state == JTTableViewCellEditingState.Left {
'JTTableViewCellEditingState.Type' does not have a member named 'Left'
Trying to do it the old, Objective-C way, like some kind of peasant, gives me a different, more expected, error:
if state == JTTableViewCellEditingStateLeft {
Cannot invoke '==' with an argument list of type '(JTTableViewCellEditingState, JTTableViewCellEditingState)'
I'm wondering how I should overcome this issue? I believe referencing Objective-C enums has worked just fine in the past.
This type of enum decleration causes problems in swift. I had similar problem. My solution is to create a helper objective-c method that does comparison and use that method in swift whenever == is needed.
Other solution may be refactor that code if you can and convert it proper enum decleration in objective-c.
typedef NS_ENUM(NSInteger, MyEnum) {
MyEnumValue1,
MyEnumValue2
};
Can you use NS_ENUM instead? And then try JTTableViewCellEditingState.JTTableViewCellEditingStateLeft or even .JTTableViewCellEditingStateLeft to access your enum. If you can't change it to NS_ENUM, please have a look at Using non NS_ENUM objective-C enum in swift
In my environment - Xcode Version 6.1.1 (6A2006):
typedef enum {
JTTableViewCellEditingStateMiddle,
JTTableViewCellEditingStateLeft,
JTTableViewCellEditingStateRight,
} JTTableViewCellEditingState;
is exported to Swift as:
struct JTTableViewCellEditingState {
init(_ value: UInt32)
var value: UInt32
}
var JTTableViewCellEditingStateMiddle: JTTableViewCellEditingState { get }
var JTTableViewCellEditingStateLeft: JTTableViewCellEditingState { get }
var JTTableViewCellEditingStateRight: JTTableViewCellEditingState { get }
So, this should works:
func gestureRecognizer(gestureRecognizer: JTTableViewGestureRecognizer!, commitEditingState state: JTTableViewCellEditingState, forRowAtIndexPath indexPath: NSIndexPath!) -> Void {
if state.value == JTTableViewCellEditingStateLeft.value {
// ...
}
}