Why C++ CLI has no default argument on managed types? - visual-c++

The following line has the error Default argument is not allowed.
public ref class SPlayerObj{
private:
void k(int s = 0){ //ERROR
}
}
Why C++ has no default argument on managed types ?
I would like to know if there is a way to fix this.

It does have optional arguments, they just don't look the same way as the C++ syntax. Optional arguments are a language interop problem. It must be implemented by the language that makes the call, it generates the code that actually uses the default argument. Which is a tricky problem in a language that was designed to make interop easy, like C++/CLI, you of course don't know what language is going to make the call. Or if it even has syntax for optional arguments. The C# language didn't until version 4 for example.
And if the language does support it, how that compiler knows what the default value is. Notable is that VB.NET and C# v4 chose different strategies, VB.NET uses an attribute, C# uses a modopt.
You can use the [DefaultParameterValue] attribute in C++/CLI. But you shouldn't, the outcome is not predictable.

In addition to the precise answer from Hans Passant, the answer to the second part on how to fix this, you are able to use multiple methods with the same name to simulate the default argument case.
public ref class SPlayerObj {
private:
void k(int s){ // Do something useful...
}
void k() { // Call the other with a default value
k(0);
}
}

An alternative solution is to use the [OptionalAttribute] along side a Nullable<int> typed parameter. If the parameter is not specified by the caller it will be a nullptr.
void k([OptionalAttribute]Nullable<int>^ s)
{
if(s == nullptr)
{
// s was not provided
}
else if(s->HasValue)
{
// s was provided and has a value
int theValue = s->Value;
}
}
// call with no parameter
k();
// call with a parameter value
k(100);

Related

Forward operators in haxe

I'm trying to write my own boolean "abstract" with some additional functions.
#forward
abstract MyBool(Bool) {
public inline function new(b:Bool) {
this = b;
}
#:from
public static inline function fromBool(b:Bool):MyBool {
return new MyBool(b);
}
#:to
public inline function toBool():Bool {
return this;
}
// some additional functions
}
In principal this works fine:
var t:T = true;
if(t) {
trace("1");
}
t.someStrangeMethod();
However #:forward does not forward basic boolean-operators like "!":
var f:T = false;
if(!f) { // fails here, because "!" is not defined as an operator for MyBool ...
trace("2");
}
The error message is "MyBool should be Bool", which I find quite strange because MyBool is an abstract of a Bool with #:forward annotation and there is a #:to-method.
Of course there are some easy workarounds. One could either use:
if(!f.toBool()) {
trace("2");
}
and/or add a function annotated with #:op(!A) to the abstract:
#:op(!A)
public inline function notOp():Bool {
return !this;
}
However I do not like both methods:
I dislike adding #:op(...) to MyBool, because creating a method for each possible operator would require much code (Maybe not with a boolean, but e.g. with an Int, Float, ...).
I dislike using !var.toBool(). If someone has already written quite some code (s)he does not want to go through all of it, when (s)he simply wants to change Bool to a MyBool ... I mean of course (s)he could also cast Bool to MyBool whenever adding new code, but that can be horrible too.
So I was wondering if anyone has a better idea? Is there maybe another "#:forward"-like compiling metadata, I do not know about yet?
There's an open feature request regarding this:
Can #:forward also forward underlying operator overloads? (#5035)
One way to make your code example work is to allow implicit conversions with to Bool. I'm not entirely sure why the equivalent #:to function doesn't work here, as the Haxe Manual states that "Class field casts have the same semantics".
abstract MyBool(Bool) to Bool {
Apart from that, I think the only options is to declare an #:op function for each operator you want to support. If declared without a body, the underlying type's operator will be forwarded:
#:op(!A) function notOp():MyBool;
If your main goal is to just add methods to the Bool type, then perhaps avoid the problem altogether by instead creating a class that adds methods to Bool via static extension (documented in the Haxe manual). This method would eliminate the need for operator forwarding.

Optional arguments on interface and class can conflict

I have just come across an interesting gotcha where optional arguments on an interface and the implementing class can conflict.
I found this out the hard way (school boy error) whilst experimenting. You cannot spot it in the debugger and I assumed it was me messing up the dependency injection.
I'm guessing this is so an alternative interface can give a differing view on what default behaviour should be?
Is there a compiler warning or style cop rule to help point this out?
public interface MyInterface
{
MyStuff Get(bool eagerLoad = true); //this overrules the implementation.
}
public class MyClass : MyInterface
{
public MyStuff Get(bool eagerLoad = false) //will still be true
{
//stuff
}
}
Remember default arguments are a compile-time feature. The compiler picks up the default argument based on the static type of the reference in question and inserts the appropriate default argument. I.e. if you reference is of the interface type you get one behavior but if the reference is of the class type you get the other in your case.

Implicit Conversion Not Working for Dynamic Type

I am running into a problem when trying to implicitly convert one of my dynamic types. There are two assemblies with definitions similar to the following:
Configuration.dll:
public class ConfigurationValue : DynamicObject
{
public ConfigurationValue(string val)
{
//...
}
//...
public static implicit operator string(ConfigurationValue val)
{
return val.ToString();
}
}
There is another class in this dll called Configuration with a member variable called Instance (to make the class singleton). This variable holds the ConfigurationValue instances in a dictionary and is of type dynamic. This allows me to do this following:
Server.dll:
//...
if (Configuration.Instance.SecurityLevel != "Insecure")
{
//...
}
Assuming that SecurityLevel is in the dictionary.
This if statement appears verbatim in my code and always fails with the following error:
{"Operator '!=' cannot be applied to operands of type 'System.Dynamic.DynamicObject' and 'string'"}
Previously, when these two classes were in the same assembly, this code worked fine. Can anyone tell me what I'm doing wrong here?
Thanks,
Max
Solved the problem, a little embarrassing actually, I forgot to change the container class for ConfigurationValue (e.g. the type of Configuration.Instance) from internal to public when I moved it to the new assembly, so of course the type couldn't be resolved and the implicit conversion was not found
Try
var SecurityLevel = new ConfigurationValue("Insecure");

inserting "this" into an STL map from the constructor

VERSION 1
class Doh {
private:
static std::map<const std::string, const Doh*> someMap;
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
}
The above was ok with MSVC 2010 but with MSVC 2008 it fails – and I guess it is because the object is not constructed yet when it is inserted in the map (I got a memory access violation).
So, I tried a delayed insertion, which worked:
VERSION 2
Doh(std::string str) : stringValue_(str) {
boost::thread(&Doh::insertIntoTheStaticMap,this);
}
void insertIntoTheStaticMap() {
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
Doh::someMap.insert(
std::make_pair<const std::string,const Doh*>
(this->stringValue_,this)
);
}
But as you might be able to guess, my intention is to have the static Doh::someMap as a common lookup dictionary.
VERSION 1 didn’t need any thread-safety because I would create all Doh instances in the same thread – in initialization blocks - which would be called by dynamic initializers before I enter main().
But with VERSION 2, the naïve sleep() is neither graceful nor reliable (not to mention, I might need to lock the map before insertion).
What would be a nice KISS approach?
Only potential issue I see is the initialization of the static member, if there are multiple source files. Try guarding it with a function.
class Doh {
private:
static std::map< std::string, Doh * > &get_map() {
static std::map< std::string, Doh * > someMap;
return someMap; // initialize upon first use
}
std::string stringValue_;
public:
Doh(std::string str) : stringValue_(str) {
get_map().insert(
std::make_pair
(this->stringValue_,this)
);
}
};
In neither version is there any sign of init for stringvalue_ - what does the debugger show you about this key when you hit the map insert in version 1 of the code? How is this field set up, and what is its type?
Running this in the debugger for VS2008 should allow you to narrow down the point of failure into the <map> source, I would have thought.

Best groovy closure idiom replacing java inner classes?

As new to groovy...
I'm trying to replace the java idiom for event listeners, filters, etc.
My working code in groovy is the following:
def find() {
ODB odb = ODBFactory.open(files.nodupes); // data nucleus object database
Objects<Prospect> src = odb.getObjects(new QProspect());
src.each { println it };
odb.close();
}
class QProspect extends SimpleNativeQuery {
public boolean match(Prospect p) {
if (p.url) {
return p.url.endsWith(".biz");
}
return false;
}
}
Now, this is far from what I'm used to in java, where the implementation of the Query interface is done right inside the odb.getObjects() method. If I where to code "java" I'd probably do something like the following, yet it's not working:
Objects<Prospect> src = odb.getObjects( {
boolean match(p) {
if (p.url) {
return p.url.endsWith(".biz");
}
return false;
}
} as SimpleNativeQuery);
Or better, I'd like it to be like this:
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
However, what groovy does it to associate the "match" method with the outer script context and fail me.
I find groovy... groovy anyways so I'll stick to learning more about it. Thanks.
What I should've asked was how do we do the "anonymous" class in groovy. Here's the java idiom:
void defReadAFile() {
File[] files = new File(".").listFiles(new FileFilter() {
public boolean accept(File file) {
return file.getPath().endsWith(".biz");
}
});
}
Can groovy be as concise with no additional class declaration?
I think it would have helped you to get answers if you'd abstracted the problem so that it didn't rely on the Neodatis DB interface -- that threw me for a loop, as I've never used it. What I've written below about it is based on a very cursory analysis.
For that matter, I've never used Groovy either, though I like what I've seen of it. But seeing as no one else has answered yet, you're stuck with me :-)
I think the problem (or at least part of it) may be that you're expecting too much of the SimpleNativeQuery class from Neodatis. It doesn't look like it even tries to filter the objects before it adds them to the returned collection. I think instead you want to use org.neodatis.odb.impl.core.query.criteria.CriteriaQuery. (Note the "impl" in the package path. This has me a bit nervous, as I don't know for sure if this class is meant to be used by callers. But I don't see any other classes in Neodatis that allow for query criteria to be specified.)
But instead of using CriteriaQuery directly, I think you'd rather wrap it inside of a Groovy class so that you can use it with closures. So, I think a Groovy version of your code with closures might look something like this:
// Create a class that wraps CriteriaQuery and allows you
// to pass closures. This is wordy too, but at least it's
// reusable.
import org.neodatis.odb.impl.core.query.criteria;
class GroovyCriteriaQuery extends CriteriaQuery {
private final c;
QProspect(theClosure) {
// I prefer to check for null here, instead of in match()
if (theClosure == null) {
throw new InvalidArgumentException("theClosure can't be null!");
}
c = theClosure;
}
public boolean match(AbstractObjectInfo aoi){
//!! I'm assuming here that 'aoi' can be used as the actual
//!! object instance (or at least as proxy for it.)
//!! (You may have to extract the actual object from aoi before calling c.)
return c(aoi);
}
}
// Now use the query class in some random code.
Objects<Prospect> src = odb.getObjects(
new GroovyCriteriaQuery(
{ it.url.endsWith(".biz") }
)
)
I hope this helps!
I believe your real question is "Can I use closures instead of anonymous classes when calling Java APIs that do not use closures". And the answer is a definite "yes". This:
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
should work. You write "However, what groovy does it to associate the "match" method with the outer script context and fail me". How exactly does it fail? It seems to me like you're having a simple technical problem to get the solution that is both "the groovy way" and exactly what you desire to work.
Yep, thanks y'all, it works.
I also found out why SimpleNativeQuery does not work (per Dan Breslau).
I tried the following and it worked wonderfully. So the idiom does work as expected.
new File("c:\\temp").listFiles({ it.path.endsWith(".html") } as FileFilter);
This next one does not work because of the neodatis interface. The interface does not enforce a match() method! It only mentions it in the documentation yet it's not present in the class file:
public class SimpleNativeQuery extends AbstactQuery{
}
Objects<Prospect> src = odb.getObjects(
{ it.url.endsWith(".biz") } as SimpleNativeQuery
);
In the above, as the SimpleNativeQuery does not have a match() method, it makes it impossible for the groovy compiler to identify which method in the SimpleNativeQuery should the closure be attached to; it then defaults to the outer groovy script.
It's my third day with groovy and I'm loving it.
Both books are great:
- Groovy Recipes (Scott Davis)
- Programming Groovy (Venkat Subramaniam)

Resources