C++/CLI ref parameter overloading - c++-cli

I have a C++/CLI value class(struct in C#) that for math.
As you know, math relevant structs are often using ref paramters for its methods for improve performance. And then, add a overloading that is non-ref version for convinience.
Such like this, in C#
public struct Vector
{
public static Vector Add(Vector left, Vector right) => Add(ref left, ref right);
public static Vector Add(ref Vector left, ref Vector right)
{
// Something.
}
}
On the other hands, in C++/CLI, I had made ref versions such like below.
public value class Vector
{
public:
static Vector Add(Vector% left, Vector% right)
{
// Something.
}
}
It has not problem. That exposing ref parameters properly in C# project.
BTW, how about non-ref version.
I can declare its prototype, but I cannot call the ref version from that.
public value class Vector
{
public:
static Vector Add(Vector left, Vector right)
{
return Add(left, right); // Compile error C2668.
}
static Vector Add(Vector% left, Vector% right)
{
// Something.
}
}
How to solve it?

What is your goal here?
If your goal is to have a API that can be called from C++/CLI, then ignoring the issue of how to implement the two versions, how would you call them from C++/CLI code? Since C++/CLI doesn't require an extra keyword when calling the ref version, you'll get error C2668 everywhere you try to use Add. In that case, I would implement the two versions with different names.
If your goal is to have an API that can be called from C#, then it might make sense to have these two methods with the same name, since C# can differentiate which one to call based on the ref keyword. In that case, I would implement Add(Vector, Vector) and Add(Vector%, Vector%) as both calling private method AddImpl(Vector%, Vector%).
I haven't checked this with a compiler. Since the way you call the methods are so similar, you may get compiler errors even after you fix the implementations. Last I checked, an unmanaged C++ compiler won't even let you define an overload along the lines of foo(int) and foo(int&), because they're called in exactly the same way. (Though I might be mis-remembering that.)
Now, all that said, let me say that this feels like a premature optimization to me. Consider implementing the 'call by value' versions only, and if your performance is acceptable, then there's no need for these extra hoops.
Also, you haven't shown your definition of what data is in your Vector type. If it's heavy-weight enough that you're considering call by reference to save time in copying the object, then perhaps the it should be changed to a reference type.

Related

Dlang: why are constructors not inherieted?

Is there a way to not have to repeatidly write this(parent class args) {super(parent class args);} when the arguments are exactly the same?
The code:
class Parent {
string name;
this(string name) {
this.name = name;
}
}
class Child : Parent {
}
unittest {
auto child = new Child("a name");
assert(child.name == "a name");
}
https://run.dlang.io/is/YnnezI
Gives me the compilation error:
Error: class onlineapp.Child cannot implicitly generate a default constructor when base class onlineapp.Parent is missing a default constructor
Java and C# don't inherit constructors either (unless that's changed in the last few years - I don't think C++ allowed it either until c++11), and D follows the same reasoning so you can read more by looking up things about them.
Basically though the reason is that subclasses must have their own unique state - at very least stuff like the vtable even if you don't declare any of your own variables - and thus a unique constructor is required. Otherwise you can have uninitialized members.
And if inheritance went the whole way, since Object has a this(), new AnyClass(); would compile and lead to a lot of invalid objects. (In regular D, if you declare any ctor with arguments, it disables the automatically-generated zero arg one.)
Now, D could in theory do what C++ does and auto-generate other args too... it just doesn't. Probably mostly because that is a relatively new idea in C++ and D's class system is primarily based on Java's older system.
But all that said, let me show you a trick:
this(Args...)(auto ref Args args) { super(args); }
stick that in your subclass and you basically inherit all the parent's constructors in one go. If the super doesn't compile for the given args, neither will this, so it doesn't add random things either. You can overload that with more specific versions if needed too, so it is a reasonable little substitute for a built-in language feature.

Accepting managed struct in C++/CLI both with "hat" operator and without. What is the difference?

I've got a C++/CLI layer that I've been using successfully for a long time. But I just discovered something that makes me think I need to relearn some stuff.
When my C++/CLI functions receive an instance of any managed class, they use the "hat" operator ('^') and when they receive an instance of a managed struct, they do not. I thought this was how I was supposed to write it.
To illustrate as blandly as I can
using Point = System::Windows::Point;
public ref class CppCliClass
{
String^ ReturnText(String^ text) { return text; } // Hat operator for class
Point ReturnStruct(Point pt) { return pt; } // No hat operator for struct
};
I thought this was required. It certainly works. But just today I discovered that CancellationToken is a struct, not a class. My code accepts it with a hat. I thought it was a class when I wrote it. And this code works just fine. My cancellations are honored in the C++/CLI layer.
void DoSomethingWithCancellation(CancellationToken^ token)
{
// Code that uses the token. It works just fine
}
So apparently I can choose either method.
But then what is the difference between passing in a struct by value (as I've done with every other struct type I use, like Point) and by reference (as I'm doing with CancellationToken?). Is there a difference?
^ for reference types and without for value types matches C#, but C++/CLI does give you more flexibility:
Reference type without ^ is called "stack semantics" and automatically tries to call IDisposable::Dispose on the object at the end of the variable's lifetime. It's like a C# using block, except more user-friendly. In particular:
The syntax can be used whether the type implements IDisposable or not. In C#, you can only write a using block if the type can be proved, at compile time, to implement IDisposable. C++/CLI scoped resource management works fine in generic and polymorphic cases, where some of the objects do and some do not implement IDisposable.
The syntax can be used for class members, and automatically implements IDisposable on the containing class. C# using blocks only work on local scopes.
Value types used with ^ are boxed, but with the exact type tracked statically. You'll get errors if a boxed value of a different type is passed in.

Passing all arguments to class constructor vs passing arguments to member functions

This question is about OOP design.
What are the advantages/disadvantages of passing all arguments to class constructor vs passing arguments to member functions ?
In my case I know all arguments in the beginning of the program and I don't need to change them until the program is over.
In C++ the situation would be something like that (although in my code I need to parse more arguments and the member functions are more complex):
// All arguments in class constructor
Rectangle::Rectangle(float base, float height, string rectColor){
this->area = 0;
this->base = base;
this->height = height;
this->rectColor = rectColor;
}
void Rectangle::calcArea(){
area = base * height;
}
void Rectangle::paintRectangle(){
// use area
// whatever
}
vs
// Arguments in member functions
Rectangle::Rectancle(){
this->area = 0;
}
void Rectangle::calcArea(float base, float height){
area = base * height;
}
void Rectangle::paintRectangle(string rectColor){
// use area
// whatever
}
One strategy that I'm using is: If I need the variable in multiple member functions I make it a class variable. Is that good or the best approach ?
A bad thing about passing everything into constructor is that it would have lots of arguments. And also I wouldn't need to call the class member functions in my main.
Please explain the main principles I should follow.
Benefits for putting arguments in the constructor:
The instance is more completely initialized (no problems with the order of functions to be called to get a 'complete'useful instance.
Benefits for putting arguments to specific functions:
More flexibility, since the functions use variables instead of 'constants' passed to the constructor
The arguments passed to functions tend to belong better to the functions (e.g. for paintRectangle it is logical to pass the color, but if it never change, why making the flexibility to change the color afterwards?)
To prevent too many arguments in the cnstructor
Create a structure to pass the variables
Create a sub class ... if you need more than 5-7 parameters, possibly the responsibility of the class is too big.
Use named arguments (more clearer, but still the same amount of arguments)
In general, make classes as limited as possible, do not make them more flexible than needed UNLESS you know beforehand the functionality is needed at a later stage.
The one of the most important thing about constructors is that they make your OOP code consistent. For any object, it is good approach, if you already know, that someone created with properties need to have to exist.
i.e. Rectangle cannot exist without "height".
Therefore the "minimum parameters constructor" is great advantage. (the minimum required parameters need to have for object, to be usable and for not able to crash, when computing i.e. area)
If you have more parameters, that they are not neccesary, it is good to create more constructors based on what is probably "often use" of your object.

Why is overriding of static methods left out of most OOP languages?

It is certainly not for good OOP design - as the need for common behavior of all instances of a derived class is quite valid conceptually. Moreover, it would make for so much cleaner code if one could just say Data.parse(file), have the common parse() code in the base class and let overriding do its magic than having to implement mostly similar code in all data subtypes and be careful to call DataSybtype.parse(file) - ugly ugly ugly
So there must be a reason - like Performance ?
As a bonus - are there OOP languages that do allow this ?
Java-specific arguments are welcome as that's what I am used to - but I believe the answer is language agnostic.
EDIT : one could ideally :
<T> void method(Iface<? extends T> ifaceImpl){
T.staticMeth(); // here the right override would be called
}
This will also fail due to erasure (in java at least) - if erasure is at work one needs (would need) to actually pass the class :
<T, K extends T> void method(Iface<K> ifaceImpl, Class<K> cls){
cls.staticMeth(); // compile error
}
Does it make sense ? Are there languages doing this already ? Is there a workaround apart from reflection ?
Speaking to C++
class Foo {
public:
static void staticFn(int i);
virtual void virtFn(int i);
};
The virtual function is a member function - that is, it is called with a this pointer from which to look up the vtable and find the correct function to call.
The static function, explicitly, does not operate on a member, so there is no this object from which to look up the vtable.
When you invoke a static member function as above, you are explicitly providing a fixed, static, function pointer.
foo->virtFn(1);
expands out to something vaguely like
foo->_vtable[0](foo, 1);
while
foo->staticFn(1);
expands to a simple function call
Foo##staticFn(1);
The whole point of "static" is that it is object-independent. Thus it would be impossible to virtualize.

Optional Parameters, Good or Bad?

I am writing and browsing through a lot of methods in the project im working with and as much as I think overloads are useful I think that having a simple optional parameter with a default value can get around the problem aiding in writing more readable and I would think efficient code.
Now I hear that using these parmeters in the methods could carry nasty side effects.
What are these side effects and is it worth the risk of using these parameters to keep the code clean ???
I'll start by prefacing my answer by saying Any language feature can be used well or it can be used poorly. Optional parameters have some drawbacks, just like declaring locals as var does, or generics.
What are these side effects
Two come to mind.
The first being that the default value for optional parameters are compile time constants that are embedded in the consumer of the method. Let's say I have this class in AssemblyA:
public class Foo
{
public void Bar(string baz = "cat")
{
//Omitted
}
}
And this in AssemblyB:
public void CallBar()
{
new Foo().Bar();
}
What really ends up being produced is this, in assemblyB:
public void CallBar()
{
new Foo().Bar("cat");
}
So, if you were to ever change your default value on Bar, both assemblyA and assemblyB would need to be recompiled. Because of this, I tend not to declare methods as public if they use optional parameters, rather internal or private. If I needed to declare it as public, I would use overloads.
The second issue being how they interact with interfaces and polymorphism. Take this interface:
public interface IBar
{
void Foo(string baz = "cat");
}
and this class:
public class Bar : IBar
{
public void Foo(string baz = "dog")
{
Console.WriteLine(baz);
}
}
These lines will print different things:
IBar bar1 = new Bar();
bar1.Foo(); //Prints "cat"
var bar2 = new Bar();
bar2.Foo(); //Prints "dog"
Those are two negatives that come to mind. However, there are positives, as well. Consider this method:
void Foo(string bar = "bar", string baz = "baz", string yat = "yat")
{
}
Creating methods that offer all the possible permutations as default would be several if not dozens of lines of code.
Conclusion: optional parameters are good, and they can be bad. Just like anything else.
Necromancing.
The thing with optional parameters is, they are BAD because they are unintuitive - meaning they do NOT behave the way you would expect it.
Here's why:
They break ABI compatibility !
(and strictly speaking, they also break API-compatiblity, when used in constructors)
For example:
You have a DLL, in which you have code such as this
public void Foo(string a = "dog", string b = "cat", string c = "mouse")
{
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
Now what kinda happens is, you expect the compiler to generate this code behind the scenes:
public void Foo(string a, string b, string c)
{
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
public void Foo(string a, string b)
{
Foo(a, b, "mouse");
}
public void Foo(string a)
{
Foo(a, "cat", "mouse");
}
public void Foo()
{
Foo("dog", "cat", "mouse");
}
or perhaps more realistically, you would expect it to pass NULLs and do
public void Foo(string a, string b, string c)
{
if(a == null) a = "dog";
if(b == null) b = "cat";
if(c == null) c = "mouse";
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
so you can change the default-arguments at one place.
But this is not what the C# compiler does, because then you couldn't do:
Foo(a:"dog", c:"dogfood");
So instead the C# compiler does this:
Everywhere where you write e.g.
Foo(a:"dog", c:"mouse");
or Foo(a:"dog");
or Foo(a:"dog", b:"bla");
It substitutes it with
Foo(your_value_for_a_or_default, your_value_for_b_or_default, your_value_for_c_or_default);
So that means if you add another default-value, change a default-value, remove a value, you don't break API-compatiblity, but you break ABI-compatibility.
So what this means is, if you just replace the DLL out of all files that compose an application, you'll break every application out there that uses your DLL. That's rather bad. Because if your DLL contains a bad bug, and I have to replace it, I have to recompile my entire application with your latest DLL. That might contain a lot of changes, so I can't do it quickly. I also might not have the old source code handy, and the application might be in a major modification, with no idea what commit the old version of the application was compiled on. So I might not be able to recompile at this time. That is very bad.
And as for only using it in PUBLIC methods, not private, protected or internal.
Yea, nice try, but one can still use private, protected or internal methods with reflection. Not because one wants to, but because it sometimes is necessary, as there is no other way. (Example).
Interfaces have already been mentioned by vcsjones.
The problem there is code-duplication (which allows for divergent default-values - or ignoring of default-values).
But the real bummer is, that in addition to that, you can now introduce API-breaking-changes in Constructors...
Example:
public class SomeClass
{
public SomeClass(bool aTinyLittleBitOfSomethingNew = true)
{
}
}
And now, everywhere where you use
System.Activator.CreateInstance<SomeClass>();
you'll now get a RUNTIME exception, because now there is NO parameter-less constructor...
The compiler won't be able to catch this at compile time.
Good night if you happen to have a lot of Activator.CreateInstances in your code.
You'll be screwed, and screwed badly.
Bonus points will be awarded if some of the code you have to maintain uses reflection to create class instances, or use reflection to access private/protected/internal methods...
Don't use optional parameters !
Especially not in class constructors.
(Disclaimer: sometimes, there simply is no other way - e.g. an attribute on a property that takes the name of the property as constructor argument automagically - but try to limit it to these few cases, especially if you can make due with overloading)
I guess theoretically they are fine for quick prototyping, but only for that.
But since prototypes have a strong tendency to go productive (at least in the company I currently work), don't use it for that, either.
I'd say that it depends how different the method becomes when you include or omit that parameter.
If a method's behaviour and internal functioning is very different without a parameter, then make it an overload. If you're using optional parameters to change behaviour, DON'T. Instead of having a method that does one thing with one parameter, and something different when you pass in a second one, have one method that does one thing, and a different method that does the other thing. If their behaviour differs greatly, then they should probably be entirely separate, and not overloads with the same name.
If you need to know whether a parameter was user-specified or left blank, then consider making it an overload. Sometimes you can use nullable values if the place they're being passed in from won't allow nulls, but generally you can't rule out the possibility that the user passed null, so if you need to know where the value came from as well as what the value is, don't use optional parameters.
Above all, remember that the optional parameters should (kinda by definition) be used for things that have a small, trivial or otherwise unimportant effect on the outcome of the method. If you change the default value, any place that calls the method without specifying a value should still be happy with the result. If you change the default and then find that some other bit of code that calls the method with the optional parameter left blank is now not working how it should, then it probably shouldn't have been an optional parameter.
Places where it can be a good idea to use optional parameters are:
Methods where it's safe to just set something to a default if a value isn't provided. This basically covers anything where the caller might not know or care what the value is. A good example is in encryption methods - the caller may just think "I don't know crypto, I don't know what value R should be set to, I just want this to be encrypted", in which case you set the defaults to sensible values. Often these start out as a method with an internal variable that you then move to be user-provided. It's pointless making two methods when the only difference is that one has var foo = bar; somewhere at the start.
Methods that have a set of parameters, but not all of them are needed. This is quite common with constructors; you'll see overloads that each set different combinations of the various properties, but if there's three or four parameters that may or may not need to be set, that can require a lot of overloads to cover all the possible combinations (it's basically a handshake problem), and all these overloads have more or less identical behaviour internally. You can solve this by having most of them just set defaults and call the one that sets all parameters, but it's less code to use optional parameters.
Methods where the coder calling them might want to set parameters, but you want them to know what a "normal" value is. For example, the encryption method we mentioned earlier might require various parameters for whatever maths goes on internally. A coder might see that they can pass in values for workFactor or blockSize, but they may not know what "normal" values are for these. Commenting and documentation will help here, but so will optional parameters - the coder will see in the signature [workFactor = 24], [blockSize = 256] which helps them judge what kind of values are sensible. (Of course, this is no excuse to not comment and document your code properly.)
You're not making more readable and efficient code.
First, your method signatures will be gratuitously longer.
Second, overloads don't exist for the sole purpose of using default values - a quick look at the Convert class should show you that. Many times overloaded methods have different execution paths, which will become spaghetti code in your single non overloaded method.
Third, sometimes you need to know whether a value was used as input. How would you then know whether the user passed those values, if he happens to use the same value as the default one you were using?
Often I see optional parameters in C# like IMyInterface parameter = null.
Especially when I see that in constructors I would even say it'S a code smell.
I know that's a hard verdict - but in this case it obscures your dependencies, which is bad.
Like vcsjones said, you can use those language features right, but I believe optional parameters should be used only in some edge-cases.
my opinion.