Which is the correct form for a C++-CLI copy constructor? - c++-cli

I have some code like this:
MyClass::MyClass(MyClass^ objToCopyFrom);
Which is producing an error:
'type' : ref class does not have a user-defined copy constructor
When I look up the error, it suggests my code should look like this:
MyClass::MyClass(MyClass% objToCopyFrom);
My question is therefore, which version is correct or are they both correct?

Only your second version is correct:
MyClass::MyClass(MyClass% objToCopyFrom);
or its variant:
MyClass::MyClass(const MyClass% objToCopyFrom);
MyClass% is a so-called Tracking Reference which is the conceptual equivalence of a reference in native C++, only for CLR types.
While copy constructors in native C++ can have a number of different signatures, what they all have in common is that the other object that's being copied is passed in as a reference. C++/CLI stays close to that principle, but uses its own type of object references, a tracking reference.

Related

abap reference variables and dynamic types

I'm fluent in ABAP and have a grasp on OO and light reference variables, but can't seem to get a deeper handle on reference variables and dynamic types etc. I've done a bit of reading, but can't seem to get the deep understanding I feel I need.
Does anyone know of some great tutorials or websites that might give clear and concise? Thanks!
First of all just google this post title and You're golden.
Second:
I'm not sure if I understand You correctly, do You want to know about such constructions as:
DATA lo_ref_var TYPE REF TO zcl_my_class.
And by dynamic types do You mean in ABAP 7.4/7.5 (ex. DATA(lv_var) = 123)?
If yes, I'll try to give You the general idea:
Reference variable is just a variable that's "ready to become" an object.
If You'll take this for example:
DATA lo_ref_var TYPE REF TO zcl_my_class.
CREATE OBJECT lo_ref_var.
Then assuming the constructor doesn't need any variables You'll get an instance of zcl_my_class Class with all it's attributes and methods. Also if You have an abstract class zcl_abs_class as a super-class and zcl_sub_class1 and zcl_sub_class2 as it's non-abstract subclass' than:
DATA:
lo_abs TYPE REF TO zcl_abs_class,
lo_sub1 TYPE REF TO zcl_sub_class1,
lo_sub2 TYPE REF TO zcl_sub_class2.
CREATE OBJECT: lo_sub1, lo_sub2.
lo_abs ?= lo_sub1.
lo_abs ?= lo_sub2.
What You can do (as seen above) is cast a subclass object to the super-class reference variable since the subclass' inherits from zcl_abs_class.
For more, do some digging.
Dynamic types:
This is in fact very simple, all You need to remember is that a variable has to have a type when being created dynamically. So for example:
DATA(lv_text) = text-000.
DATA(lv_int) = 1.
Line with lv_text will not work (will not compile) since text-000 does not have a precise type.
The second line on the other hand will take the type I.
If one would like to decide which type to choose You can do this by writing:
DATA(lv_bukrs) = CONV bukrs( '1234' ).
You can even use the type that an already existing variable has by writing:
DATA(lv_bukrs2) = CONV #( lv_bukrs ).
since the "#" means "use the type of variable inside brackets".
Hope this will help You start :)

What is the point of CTypeDynamic?

I'm using reflection to serialize an object. Getting the values as objects is a real murder on performance due to late binding penalties. CType / DirectCast can get rid of most of it but I can't feed a type variable into it so currently I'm using a switch case block on the type variable to select the correct DirectCast.
It came to my attention that CTypeDynamic exists and takes type variables but the return type is Object so... it converts an object into an object, cool. That got me wondering, what is the purpose of this function?
The CTypeDynamic function looks for dynamic information and performs the cast/conversion appropriately. This is different from the CType operator which looks for static information at compile time or relies on the types being IConvertible.
This function examines the object at runtime including looking for Shared (aka static) custom operators. As always, if you know the type then use CType, but if you need dynamic casting then you need to use CTypeDynamic.
More information here: http://blogs.msmvps.com/bill/2010/01/24/ctypedynamic/

Matching Roslyn SourceMemberMethodSymbol with a 'RetargetingMethodSymbol'

I've been putting some 'find references' code together using Roslyn to search for all method declarations that match a particular signature, and then locate all uses of those methods elsewhere.
It's working in 99% of cases, but I've got an issue where an InvocationExpressionSyntax.Symbol is an instance of Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting.RetargetingMethodSymbol instead of a regular Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberMethodSymbol. As a consequence this particular call to a target method isn't found (using ISymbol.Equals, which uses reference equality). RetargetingMethodSymbol has an UnderlyingMethod property whose value is the target method I'd expect, but this type is internal and that property isn't exposed.
What is a RetargetingMethodSymbol, and how can I see if it corresponds to a MethodBlockSyntax.Symbol?
What is a RetargetingMethodSymbol?
Consider a method M(object o) that is defined in project A, which targets .NET 2.0.
Project B targets .NET 4.0, and has a reference to A. In the context of project B, M will be wrapped in a RetargetingMethodSymbol, since the object that it refers to in this context isn't the same one that it refers to in the context of A.
How can I see if it corresponds to a MethodBlockSyntax.Symbol?
I don't know what you mean by MethodBlockSyntax.Symbol, but the VS IDE code uses SymbolFinder.FindSourceDefinitionAsync() to find the "original" symbol in cases like this (and also if A was written in C# and B in VB or vice versa).

CLI/C++ function overload

I am currently writing a wrapper for a native C++ class in CLI/C++. I am on a little GamePacket class at the moment. Consider the following class:
public ref class GamePacket
{
public:
GamePacket();
~GamePacket();
generic<typename T>
where T : System::ValueType
void Write(T value)
{
this->bw->Write(value);
}
};
I want that I'm able to call the function as following in C#, using my Wrapper:
Packet.Write<Int32>(1234);
Packet.Write<byte>(1);
However, I can't compile my wrapper. Error:
Error 1 error C2664: 'void System::IO::BinaryWriter::Write(System::String ^)' : cannot convert argument 1 from 'T' to 'bool'
I don't understand this error, where does the System::String^ comes from. I'm seeing a lot of overloads of the Write() method, does CLI/C++ not call the correct one, and if so, how can I make it call the correct one?
Reference MSDN: http://msdn.microsoft.com/en-us/library/system.io.binarywriter.write(v=vs.110).aspx
Templates and generics don't work the same.
With templates, the code gets recompiled for each set of parameters, and the results can be pretty different (different local variable types, different function overloads selected). Specialization makes this really powerful.
With generics, the code only gets compiled once, and the overload resolution is done without actually knowing the final parameters. So when you call Write(value), the only things the compiler knows is that
value can be converted to Object^, because everything can
value derives from ValueType, because your constraint tells it
Unfortunately, using just that information, the compiler can't find an overload of Write that can be used.
It seems like you expected it to use Write(bool) when T is bool, Write(int) when T is int, and so on. Templates would work like that. Generics don't.
Your options are:
a dozen different copies of your method, each of which has a fixed argument type that can be used to select the right overload of BinaryWrite::Write
find the overload yourself using reflection, make a delegate matching the right overload, and call it
use expression trees or the dynamic language runtime to find and make a delegate matching the right overload, and then you call it

System.Linq.Dynamic ´s .Where will be misinterpreted

I've build a large program with many references. F.e.:
System.Data.DataSetExtensions
System.Linq.Dynamic
I've to write a Dynamic Linq Expression:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
In my case:
Dim query As IEnumerable = ds.Sales.Where(strWhere)
But with System.Data.DataSetExtensions Where is misinterpreted. The compiler expects (Datarow, Integer, Boolean). If I delete System.Data.DataSetExtensions everything is ok with this expression, but I get many other errors, so I need this reference.
What can I do that the Where is interpreted correctly?
Is the large programm all in one file?
If not done already, split up your program into classes, then put each class into it's own file. Then only use the required references in every file.
Maybe this way you will be able to resolve the namespace conflict.
If for some reason you absolutely need both conflicting namespaces and can't resolve the ambiguity, you can directly call the extension method. Basically the extension method is just another static method on another class. ds.Sales.Where(strWhere) is only syntactic sugar for that method call.
An example:
ds.Sales.AsEnumerable().Where(yourCondition)
Would translate to
EnumerableRowCollectionExtensions.Where(ds.Sales.AsEnumerable(), yourCondition)