Is it possible to create and use custom System::String^ extension methods in C++/CLI? - c++-cli

I tried making an extension to the built-in String class using C++/CLI, and using it from C++/CLI without success.
Here's the simplest I can boil it down to:
[System::Runtime::CompilerServices::Extension]
public ref class MyStringExtensions abstract sealed {
public:
[System::Runtime::CompilerServices::Extension]
static bool TestMethod(System::String^ str) { return false; }
};
Now, when I try to use this in other C++/CLI code, I get a compiler message indicating that TestMethod is not a method of String.
String^ foo = gcnew ...
...
blah = foo->TestMethod(); // compile-error
Any ideas?

C++ doesn't have extension methods.
But it does have ADL (Argument-dependent lookup, also known as Koenig lookup) which is arguably even nicer.

Related

How to force invoke method with object type input value without any type casting in a series of overloaded methods?

For example I'm having a class with three overloaded methods like this:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
// Method implementation.
}
}
My question is when I call the sum method of MyClass by passing any value (integer, string or object) it should invoke only third method (with object type input parameter)
class MainClass
{
static void Main(string[] args)
{
MyClass obj = new MyClass();
obj.sum(10);
obj.sum("X")
}
}
You said "without type casting" but you can't, because you need some way to indicate to the compiler which version to call, and the runtime uses the type it sees to do that bit. Boxing the int as an object means the compiler will pick the object version
sum(1);//call int version
sum((object)1); //call object version
sum((string)(object)"1"); //call string version
sum((object)(int)(object)1); //call object version
First of all, let me say that if you sometimes want to call one version of the sum function when working with ints and sometimes want to call another, overloading probably isn't the right tool to use. Overloading works best when you are implementing conceptually the same operation for a number of different types, and you want the compiler to figure out automatically which function is the right one to call for each type; if you need more manual control over which function is called, you're probably better off using different names.
That said, if you're sure that this is what you want to do, you could implement the overloaded version for object in terms of another function in the public interface, as in:
class MyClass
{
int sum(int i)
{
// Method implementation.
}
int sum(string x)
{
// Method implementation.
}
int sum(object o)
{
sum_object(o);
}
int sum_object(object o)
{
// Method implementation for objects
}
}
Then, when you want to apply the object version to int and string objects, you just call sum_object directly instead.

What's the purpose of allowing the declaration of an abstract method in a non-abstract class?

According to this article, it's possible, in Dart, to define a non-abstract class to have an abstract (or not-implemented) method. The abstract method causes a warning, but does not prevent instantiation.
What's the purpose of allowing the declaration of an abstract method in a non-abstract (or concrete) class in Dart? Why was Dart designed to work in this way?
The specification is actually very explicit about declaring abstract methods in a concrete class:
It is a static warning if an abstract member m is declared or inherited in a concrete class
We wish to warn if one declares a concrete class with abstract members.
It is a static warning if a concrete class has an abstract member (declared or inherited).
They don't have any intended purpose for it, which is why they issue warnings. If you're familiar with Java: it's similar to accessing a static member via an object, which is also pointless and triggers a warning.
As for why it passes compilation, Dart uses an optional type system, which means typing concepts should not affect the semantics of the language, and that's simply what Dart is enforcing:
The purpose of an abstract method is to provide a declaration for purposes such as type checking and reflection.
The static checker will report some violations of the type rules, but such violations do not abort compilation or preclude execution.
An abstract method in a concrete class allows you to provide the type signature for a method that is implemented via noSuchMethod() instead. Providing a noSuchMethod() implementation will also silence the warning.
In strong mode, simply having an abstract method in a concrete class will result in an error, unless the class also implements the noSuchMethod() interface.
In short, the purpose of abstract methods in a concrete class is to provide type signatures for noSuchMethod() implementations. This avoids warnings for calling an unknown method and in strong mode (which is the default for dartdevc, and will be first the default and then mandatory for Dart 2.0) these type signatures are necessary for code with noSuchMethod() to even compile, unless the target is of type dynamic.
Example:
class A {
void f();
dynamic noSuchMethod(Invocation inv) => null;
}
void main() {
var a = new A();
a.f();
}
If we replace a.f() with (say) a.f(0), then this will result in an error (in strong mode) for having called the method with the wrong number of parameters. If we omit the void f() declaration, then we'll get an error that A does not have a method f(). If we omit the noSuchMethod() implementation, then the complaint will be that f() lacks a method body, even though A isn't abstract.
The following code provides a more realistic example:
import "dart:mirrors";
class DebugList<T> implements List<T> {
List<T> _delegate;
InstanceMirror _mirror;
DebugList(this._delegate) {
_mirror = reflect(_delegate);
}
dynamic noSuchMethod(Invocation inv) {
print("entering ${inv.memberName}");
var result = _mirror.delegate(inv);
print("leaving ${inv.memberName}");
return result;
}
}
void main() {
List<int> list = new DebugList<int>([1, 2, 3]);
int len = list.length;
for (int i = 0; i < len; i++) print(list[i]);
}
This example creates a debugging decorator for List<T>, showing all method invocations. We use implements List<T> to pull in the entire list interface, inheriting dozens of abstract methods. This would normally result in warnings (or in strong mode, errors) when run through dartanalyzer, as we're missing implementations for all these methods normally provided by List<T>. Providing a noSuchMethod() implementation silences these warnings/errors.
While we could also manually wrap all 50+ methods, this would be a lot of typing. The above approach also will continue to work if new methods are added to the list interface without us having to change our code.
Use cases for explicitly listing methods in a concrete class are less common, but can also occur. An example would be the addition of getters or setters to such a debugging decorator that allows us to inspect or set instance variables of the delegate. We will need to add them to the interface, anyway, to avoid warnings and errors from using them; the noSuchMethod() implementation can then implement them using getField() and setField(). Here's a variant of the previous example, using stacks instead of lists:
// main.dart
import "dart:mirrors";
import "stack.dart";
class DebugStack<T> implements Stack<T> {
Stack<T> _delegate;
InstanceMirror _mirror;
DebugStack(this._delegate) {
_mirror = reflect(_delegate);
}
dynamic _get(Symbol sym) {
// some magic so that we can retrieve private fields
var name = MirrorSystem.getName(sym);
var sym2 = MirrorSystem.getSymbol(name, _mirror.type.owner);
return _mirror.getField(sym2).reflectee;
}
List<T> get _data;
dynamic noSuchMethod(Invocation inv) {
dynamic result;
print("entering ${inv.memberName}");
if (inv.isGetter)
result = _get(inv.memberName);
else
result = _mirror.delegate(inv);
print("leaving ${inv.memberName}");
return result;
}
}
void main() {
var stack = new DebugStack<int>(new Stack<int>.from([1, 2, 3]));
print(stack._data);
while (!stack.isEmpty) {
print(stack.pop());
}
}
// stack.dart
class Stack<T> {
List<T> _data = [];
Stack.empty();
Stack.from(Iterable<T> src) {
_data.addAll(src);
}
void push(T item) => _data.add(item);
T pop() => _data.removeLast();
bool get isEmpty => _data.length == 0;
}
Note that the abstract declaration of the _data getter is crucial for type checking. If we were to remove it, we'd get a warning even without strong mode, and in strong mode (say, with dartdevc or dartanalyzer --strong), it will fail:
$ dartdevc -o main.js main.dart
[error] The getter '_data' isn't defined for the class 'DebugStack<int>' (main.dart, line 36, col 15)
Please fix all errors before compiling (warnings are okay).

Should C++/CLI data members be handles or values?

I'm new to C++/CLI and I'm wondering what is "best practice" regarding managed type data members. Declaring as handle:
public ref class A {
public:
A() : myList(gcnew List<int>()) {}
private:
List<int>^ myList;
};
or as a value:
public ref class B {
private:
List<int> myList;
};
Can't seem to find definitive advice on this.
When writing managed C++ code, I'm in favor of following the conventions used by the other managed languages. Therefore, I'd go with handles for class-level data members, and only use values (stack semantics) where you'd use a using statement in C#.
If your class member is a value, then replacing the object entirely means that the object would need a copy constructor defined, and not many .NET classes do. Also, if you want to pass the object to another method, you'll need to use the % operator to convert from List<int> to List<int>^. (Not a big deal to type %, but easy to forget, and the compiler error just says it can't convert List<int> to List<int>^.)
//Example of the `%` operator
void CSharpMethodThatDoesSomethingWithAList(List<int>^ list) { }
List<int> valueList;
CSharpMethodThatDoesSomethingWithAList(%valueList);
List<int>^ handleList = gcnew List<int>();
CSharpMethodThatDoesSomethingWithAList(handleList);
It all depends on the lifetime. When you have a private member which lives exactly as long as the owning class, the second form is preferable.
Personally, I would use the second form. I say this because I use frameworks that are written by other teams of people, and they use this form.
I believe this is because it is cleaner, uses less space, and is easier for the non-author to read. I try to keep in mind that the most concise code, while still being readable by someone with minimal knowledge of the project is best.
Also, I have not encountered any problems with the latter example in terms of readability across header files, methods, classes, or data files ...etc
Though I'm FAR from an expert in the matter, that is what I prefer. Makes more sense to me.
class AlgoCompSelector : public TSelector {
public :
AlgoCompSelector( TTree *tree = 0 );
virtual ~AlgoCompSelector(){ /* */ };
virtual void Init(TTree *tree);
virtual void SlaveBegin(TTree *tree);
virtual Bool_t Process(Long64_t entry);
virtual void Terminate();
virtual Int_t Version() const { return 1; }
void setAlgo( Int_t idx, const Char_t *name, TTree* part2, TTree* part3 );
void setPTthres( Float_t val );
void setEthres( Float_t val );
private:
std::string mAlgoName[2]; // use this for the axis labels and/or legend labels.
TTree *mPart1;
TTree *mPart2[2], *mPart3[2]; // pointers to TTrees of the various parts
TBranch *mPhotonBranch[2]; // Used branches
TClonesArray *mPhotonArray[2]; // To point to the array in the tree
for example

Capturing return type of unmanaged class using C++/CLI

I have a method in my native dll, that I want to use. The method returns an object of a type that is also in my native dll.I am trying to write a c++/CLI wrapper.
Now,
Can I get a return value as the object using C++/CLI and how do I do that?
Can we store and pass the native C++ object?
Should I need to create my own class resembling the native C++ class?
How would I marshal a class?
For Example,My native dll has these classes,
class X
{
/* some props and methods. */
};
Class Y
{
X* someMethod();
};
I need to wrap the someMethod class using C++/CLI. Will I be able to get the return value in the CLI?
Returning pointers to C++ objects from an exported function in a DLL is a pretty bad idea. It is a nasty memory management problem, you'd expect the client code to release the object. That can only come to a good end when both DLLs use the exact same version of the DLL version of the CRT (/MD compile option). If you can't recompile the native DLL then stop right now, you cannot make it work reliably or you'll have a big maintenance problem in the future.
Anyhoo, you need a wrapper for both classes. They should resemble this:
#pragma managed(push, off)
#include "xandy.h"
#pragma managed(pop)
using namespace System;
namespace something {
public ref class XWrapper {
X* mX;
public:
XWrapper(X* obj) : mX(obj) {}
~XWrapper() { this->!XWrapper(); }
!XWrapper() {
// Trouble is here!!!
delete mX;
}
};
public ref class YWrapper {
Y* mY;
public:
YWrapper() { mY = new Y; }
~YWrapper() { this->!YWrapper(); }
!YWrapper() { delete mY; }
XWrapper^ someMethod() {
return gcnew XWrapper(mY->someMethod());
}
};
}

How to fix warning CA2226 in a C++/CLI application?

I have a C++/CLI class definition where I'm trying to get Equality testing to be Value based rahter than Reference (similar to the behavior of String). The following definitions work:
namespace MyCode
{
public ref class MyClass
{
public:
MyClass();
bool operator==(MyClass^ obj) { return Equals(obj); }
bool operator!=(MyClass^ obj) { return !Equals(obj); }
virtual bool Equals(MyClass^ obj);
virtual bool Equals(System::Object^ obj) override;
virtual int GetHashCode() override;
};
}
However, my company is now requiring (and rightly so) that all code needs to conform to the Code Analysis rules. Code analysis consistently reports two warnings on the above class:
CA2226 : Microsoft.Usage : Since ''MyClass'' redefines operator '==', it should also redefine operator '!='.
CA2226 : Microsoft.Usage : Since ''MyClass'' redefines operator '!=', it should also redefine operator '=='.
The Microsoft documentation on warning CA2226 makes it clear that this is an important warning and should not be suppressed - but what else can I do?
I'm looking for a way (if possible) to 'fix' the code in order to remove this warning. Is that possible, or do I just need to suppress it?
For a ref class, you're supposed to implement operator==(MyClass^ left, MyClass^ right) as a static member function, this is the one other .NET languages will find.
Your current implementation defines operator==(MyClass%, MyClass^ right) instead, which is unusual.
Note that you can't rely on left != nullptr, you need to test ReferenceEquals(left, nullptr).
This is a .NET implementation detail. Having instance operator overloads is a C++ feature, the code analyzer chokes on it. The .NET way is to have operator overloads as static functions. Notably C# requires this. Solve your problem similar to this:
static bool operator==(MyClass^ lhs, MyClass^ rhs) { return lhs->Equals(rhs); }
static bool operator!=(MyClass^ lhs, MyClass^ rhs) { return !lhs->Equals(rhs); }