Advertisement

Global References

Started by February 14, 2014 09:15 PM
9 comments, last by WitchLord 10 years, 8 months ago

I have a reference object without a copy factory. I get a compiler error when passing an instance of that object to a function that takes a const &in reference when the object is a global variable but not when it is a local variable. Is this a bug or a feature?


MyObject x;

void main()
{
    myFunc(x);  // Compile error: There is no copy operator for the type 'MyObject' available.  
}

void myFunc(const MyObject &in y)
{
    // Do something
}

void main()
{
    MyObject x;
    myFunc(x);  // Compiles successfully
}

void myFunc(const MyObject &in y)
{
    // Do something
}

I'll need to look into this.

By default, you should think of &in references as working the same as by-value except that the calling convention is that the value is passed as reference.

But, since the &in reference in this case is const it does look like a bug, or rather a compiler path with opportunity for optimization as there is no need to copy the object in order to guarantee that the original isn't modified by the function.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I understand that, generally, &in references should be effectively the same as by-value. My main purpose for posting is to point out that the "const in&" behavior seems to works differently depending on scope, which seems like a bug.

My real issue is, in order to simulate variable arguments, I register about ten functions with the following prototypes:

Print(const ?&in);

Print(const ?&in, const ?&in);

...

I need this prototype work work for any type, whether a literal or a variable, and it needs to allow variable to pass by const reference so that it will work on objects that do not have copy constructors.

I would use "const ?&", but that doesn't work for literals (Error: Not a valid reference).

I welcome any alternatives. Thanks.

It's a bit contradictory. ?&in means that the function should receive a reference to a copy of the value so it is free to modify it without worrying about affecting the original value. And you say you want to be able to send a value to a type that doesn't allow copies to be made. :)

I will probably be able to change the compiler to allow const ?&in to take a reference without requiring the copy to be made first. At least, for reference types where it is possible to guarantee the lifetime by holding on to a handle (for value types it is not always possible to avoid the copy). But it would really only be an optimization, and not really what the compiler should be doing in the strict sense of it.

In reality, what you really need is for the compiler to support overloads with ?&in for value types and just ?& for reference types. Maybe even ?@&in specifically for handles. This is something I've already planned, but is not a trivial change so it will probably be a while before I get to it.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

It is a bit contradictory. "const ?&in" was the lessor of two evils. What I really want is "const &" behavior like C++, which is pretty much what you describe with "?&in" for value types and "const ?&" for reference types.

Do you have any recommendations for a Print function that can take any type? If I use Print(const ?&) then I cannot pass value types. If I use Print(const ?&in) then I cannot pass reference types that do not copy. I don't think I can register both types, and I can't really expect my script writers to be able to distinguish value types from reference types.

For now, my recommendation is to wait until I've been able to change the code for 'const ?&in' so the compiler doesn't need to copy the value for reference types. This I should be able to include in version 2.28.2 unless I hit some currently unforseen obstacle.

Or, if you don't care about perfect sandbox security in the scripts, you can turn on asEP_ALLOW_UNSAFE_REFERENCES, and use 'const ?&' for both value types and references types. If you trust your script writers not to do anything dumb, the unsafe references are just as safe as in C++.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Advertisement

I am using asEP_ALLOW_UNSAFE_REFERENCES, which does work for value types, but it does not work for literal values. Print(3.5), for example, fails with "Not a valid reference". Maybe I can investigate creating a copy for literal values being passed as "const &"

I looked into allowing literals to make a temporary copy when being passed as "const &inout". I think that will allow me to use "const &" until you make the change to not make "const ?&in" create a copy for reference types. I don't know if this is something you would want to incorporate officially or not. If not, I'll remove this patch and convert my "const ?&" to "const ?&in" as appropriate.

I'll check it out.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

I've included this in revision 1861.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement