300 lines
14 KiB
HTML
300 lines
14 KiB
HTML
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
|
||
|
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
|
||
|
<meta name="generator" content="Doxygen 1.8.18"/>
|
||
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||
|
<title>AngelScript: Operator overloads</title>
|
||
|
<link href="tabs.css" rel="stylesheet" type="text/css"/>
|
||
|
<script type="text/javascript" src="jquery.js"></script>
|
||
|
<script type="text/javascript" src="dynsections.js"></script>
|
||
|
<link href="navtree.css" rel="stylesheet" type="text/css"/>
|
||
|
<script type="text/javascript" src="resize.js"></script>
|
||
|
<script type="text/javascript" src="navtreedata.js"></script>
|
||
|
<script type="text/javascript" src="navtree.js"></script>
|
||
|
<link href="search/search.css" rel="stylesheet" type="text/css"/>
|
||
|
<script type="text/javascript" src="search/searchdata.js"></script>
|
||
|
<script type="text/javascript" src="search/search.js"></script>
|
||
|
<script type="text/javascript">
|
||
|
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */
|
||
|
$(document).ready(function() { init_search(); });
|
||
|
/* @license-end */
|
||
|
</script>
|
||
|
<link href="doxygen.css" rel="stylesheet" type="text/css" />
|
||
|
</head>
|
||
|
<body>
|
||
|
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
|
||
|
<div id="titlearea">
|
||
|
<table cellspacing="0" cellpadding="0">
|
||
|
<tbody>
|
||
|
<tr style="height: 56px;">
|
||
|
<td id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
|
||
|
<td id="projectalign" style="padding-left: 0.5em;">
|
||
|
<div id="projectname">AngelScript
|
||
|
</div>
|
||
|
</td>
|
||
|
<td> <div id="MSearchBox" class="MSearchBoxInactive">
|
||
|
<span class="left">
|
||
|
<img id="MSearchSelect" src="search/mag_sel.png"
|
||
|
onmouseover="return searchBox.OnSearchSelectShow()"
|
||
|
onmouseout="return searchBox.OnSearchSelectHide()"
|
||
|
alt=""/>
|
||
|
<input type="text" id="MSearchField" value="Search" accesskey="S"
|
||
|
onfocus="searchBox.OnSearchFieldFocus(true)"
|
||
|
onblur="searchBox.OnSearchFieldFocus(false)"
|
||
|
onkeyup="searchBox.OnSearchFieldChange(event)"/>
|
||
|
</span><span class="right">
|
||
|
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
|
||
|
</span>
|
||
|
</div>
|
||
|
</td>
|
||
|
</tr>
|
||
|
</tbody>
|
||
|
</table>
|
||
|
</div>
|
||
|
<!-- end header part -->
|
||
|
<!-- Generated by Doxygen 1.8.18 -->
|
||
|
<script type="text/javascript">
|
||
|
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */
|
||
|
var searchBox = new SearchBox("searchBox", "search",false,'Search');
|
||
|
/* @license-end */
|
||
|
</script>
|
||
|
</div><!-- top -->
|
||
|
<div id="side-nav" class="ui-resizable side-nav-resizable">
|
||
|
<div id="nav-tree">
|
||
|
<div id="nav-tree-contents">
|
||
|
<div id="nav-sync" class="sync"></div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div id="splitbar" style="-moz-user-select:none;"
|
||
|
class="ui-resizable-handle">
|
||
|
</div>
|
||
|
</div>
|
||
|
<script type="text/javascript">
|
||
|
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */
|
||
|
$(document).ready(function(){initNavTree('doc_script_class_ops.html',''); initResizable(); });
|
||
|
/* @license-end */
|
||
|
</script>
|
||
|
<div id="doc-content">
|
||
|
<!-- window showing the filter options -->
|
||
|
<div id="MSearchSelectWindow"
|
||
|
onmouseover="return searchBox.OnSearchSelectShow()"
|
||
|
onmouseout="return searchBox.OnSearchSelectHide()"
|
||
|
onkeydown="return searchBox.OnSearchSelectKey(event)">
|
||
|
</div>
|
||
|
|
||
|
<!-- iframe showing the search results (closed by default) -->
|
||
|
<div id="MSearchResultsWindow">
|
||
|
<iframe src="javascript:void(0)" frameborder="0"
|
||
|
name="MSearchResults" id="MSearchResults">
|
||
|
</iframe>
|
||
|
</div>
|
||
|
|
||
|
<div class="PageDoc"><div class="header">
|
||
|
<div class="headertitle">
|
||
|
<div class="title">Operator overloads </div> </div>
|
||
|
</div><!--header-->
|
||
|
<div class="contents">
|
||
|
<div class="textblock"><p>It is possible to define what should be done when an operator is used with a script class. While not necessary in most scripts it can be useful to improve readability of the code.</p>
|
||
|
<p>This is called operator overloading, and is done by implementing specific class methods. The compiler will recognize and use these <br />
|
||
|
methods when it compiles expressions involving the overloaded operators and the script class.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_unary_ops"></a>
|
||
|
Prefixed unary operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>- </td><td>opNeg </td></tr>
|
||
|
<tr>
|
||
|
<td>~ </td><td>opCom </td></tr>
|
||
|
<tr>
|
||
|
<td>++ </td><td>opPreInc </td></tr>
|
||
|
<tr>
|
||
|
<td>-- </td><td>opPreDec </td></tr>
|
||
|
</table>
|
||
|
<p>When the expression <code><em>op</em> a</code> is compiled, the compiler will rewrite it as <code>a.<em>opfunc</em>()</code> and compile that instead.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_unary2_ops"></a>
|
||
|
Postfixed unary operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>++ </td><td>opPostInc </td></tr>
|
||
|
<tr>
|
||
|
<td>-- </td><td>opPostDec </td></tr>
|
||
|
</table>
|
||
|
<p>When the expression <code>a <em>op</em></code> is compiled, the compiler will rewrite it as <code>a.<em>opfunc</em>()</code> and compile that instead.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_cmp_ops"></a>
|
||
|
Comparison operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>== </td><td>opEquals </td></tr>
|
||
|
<tr>
|
||
|
<td>!= </td><td>opEquals </td></tr>
|
||
|
<tr>
|
||
|
<td>< </td><td>opCmp </td></tr>
|
||
|
<tr>
|
||
|
<td><= </td><td>opCmp </td></tr>
|
||
|
<tr>
|
||
|
<td>> </td><td>opCmp </td></tr>
|
||
|
<tr>
|
||
|
<td>>= </td><td>opCmp </td></tr>
|
||
|
<tr>
|
||
|
<td>is </td><td>opEquals </td></tr>
|
||
|
<tr>
|
||
|
<td>!is </td><td>opEquals </td></tr>
|
||
|
</table>
|
||
|
<p>The <code>a == b</code> expression will be rewritten as <code>a.opEquals(b)</code> and <code>b.opEquals(a)</code> and then the best match will be used. <code>!=</code> is treated similarly, except that the result is negated. The opEquals method must be implemented to return a <code>bool</code> in order to be considered by the compiler.</p>
|
||
|
<p>The comparison operators are rewritten as <code>a.opCmp(b) <em>op</em> 0</code> and <code>0 <em>op</em> b.opCmp(a)</code> and then the best match is used. The opCmp method must be implemented to return a <code>int</code> in order to be considered by the compiler. If the method argument is to be considered larger than the object then the method should return a negative value. If they are supposed to be equal the return value should be 0.</p>
|
||
|
<p>If an equality check is made and the opEquals method is not available the compiler looks for the opCmp method instead. So if the opCmp method is available it is really not necesary to implement the opEquals method, except for optimization reasons.</p>
|
||
|
<p>The identity operator, <code>is</code>, expects opEquals to take a handle, <code>@</code>, so the addresses can be compared to be able to return if it is the same object, in contrast two different objects that have the same value.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_assign_ops"></a>
|
||
|
Assignment operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>= </td><td>opAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>+= </td><td>opAddAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>-= </td><td>opSubAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>*= </td><td>opMulAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>/= </td><td>opDivAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>%= </td><td>opModAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>**= </td><td>opPowAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>&= </td><td>opAndAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>|= </td><td>opOrAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>^= </td><td>opXorAssign </td></tr>
|
||
|
<tr>
|
||
|
<td><<= </td><td>opShlAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>>>= </td><td>opShrAssign </td></tr>
|
||
|
<tr>
|
||
|
<td>>>>= </td><td>opUShrAssign </td></tr>
|
||
|
</table>
|
||
|
<p>The assignment expressions <code>a <em>op</em> b</code> are rewritten as <code>a.<em>opfunc</em>(b)</code> and then the best matching method is used. An assignment operator can for example be implemented like this:</p>
|
||
|
<pre>
|
||
|
obj@ opAssign(const obj &in other)
|
||
|
{
|
||
|
// Do the proper assignment
|
||
|
...</pre><pre> // Return a handle to self, so that multiple assignments can be chained
|
||
|
return this;
|
||
|
}
|
||
|
</pre><p>All script classes have a default assignment operator that does a bitwise copy of the content of the class, so if that is all you want to do, then there is no need to implement this method.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_binary_ops"></a>
|
||
|
Binary operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b></td><td><b>opfunc_r</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>+ </td><td>opAdd </td><td>opAdd_r </td></tr>
|
||
|
<tr>
|
||
|
<td>- </td><td>opSub </td><td>opSub_r </td></tr>
|
||
|
<tr>
|
||
|
<td>* </td><td>opMul </td><td>opMul_r </td></tr>
|
||
|
<tr>
|
||
|
<td>/ </td><td>opDiv </td><td>opDiv_r </td></tr>
|
||
|
<tr>
|
||
|
<td>% </td><td>opMod </td><td>opMod_r </td></tr>
|
||
|
<tr>
|
||
|
<td>** </td><td>opPow </td><td>opPow_r </td></tr>
|
||
|
<tr>
|
||
|
<td>& </td><td>opAnd </td><td>opAnd_r </td></tr>
|
||
|
<tr>
|
||
|
<td>| </td><td>opOr </td><td>opOr_r </td></tr>
|
||
|
<tr>
|
||
|
<td>^ </td><td>opXor </td><td>opXor_r </td></tr>
|
||
|
<tr>
|
||
|
<td><< </td><td>opShl </td><td>opShl_r </td></tr>
|
||
|
<tr>
|
||
|
<td>>> </td><td>opShr </td><td>opShr_r </td></tr>
|
||
|
<tr>
|
||
|
<td>>>> </td><td>opUShr </td><td>opUShr_r </td></tr>
|
||
|
</table>
|
||
|
<p>The expressions with binary operators <code>a <em>op</em> b</code> will be rewritten as <code>a.<em>opfunc</em>(b)</code> and <code>b.<em>opfunc_r</em>(a)</code> and then the best match will be used.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_index_op"></a>
|
||
|
Index operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>[] </td><td>opIndex </td></tr>
|
||
|
</table>
|
||
|
<p>When the expression <code>a[i]</code> is compiled, the compiler will rewrite it as <code>a.opIndex(i)</code> and compile that instead. Multiple arguments between the brackets is also supported.</p>
|
||
|
<p>The index operator can also be formed similarly to <a class="el" href="doc_script_class_prop.html">property accessors</a>. The get accessor should then be named <code>get_opIndex</code> and have one parameter for the indexing. The set accessor should be named <code>set_opIndex</code> and have two parameters, the first is for the indexing, and the second for the new value.</p>
|
||
|
<pre>
|
||
|
class MyObj
|
||
|
{
|
||
|
float get_opIndex(int idx) const { return 0; }
|
||
|
void set_opIndex(int idx, float value) { }
|
||
|
}
|
||
|
</pre><p>When the expression <code>a[i]</code> is used to retrieve the value, the compiler will rewrite it as <code>a.get_opIndex(i)</code>. When the expression is used to set the value, the compiler will rewrite it as <code>a.set_opIndex(i, expr)</code>.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_call"></a>
|
||
|
Functor operator</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="80"><b>op</b></td><td width="120"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td>() </td><td>opCall </td></tr>
|
||
|
</table>
|
||
|
<p>When the expression <code>expr(arglist)</code> is compiled and expr evaluates to an object, the compiler will rewrite it as <code>expr.opCall(arglist)</code> and compile that instead.</p>
|
||
|
<h1><a class="anchor" id="doc_script_class_conv"></a>
|
||
|
Type conversion operators</h1>
|
||
|
<table cellspacing="0" cellpadding="0" border="0">
|
||
|
<tr>
|
||
|
<td width="150"><b>op</b></td><td width="300"><b>opfunc</b> </td></tr>
|
||
|
<tr>
|
||
|
<td><em>type</em>(<em>expr</em>)</td><td><em>constructor</em>, opConv, opImplConv </td></tr>
|
||
|
<tr>
|
||
|
<td>cast<<em>type</em>>(<em>expr</em>)</td><td>opCast, opImplCast </td></tr>
|
||
|
</table>
|
||
|
<p>When the expression <code>type(expr)</code> is compiled and type doesn't have a constructor that take an argument with the type of the expression, the compiler will try to rewrite it as <code>expr.opConv()</code>. The compiler will then chose the opConv that returns the desired type.</p>
|
||
|
<p>For implicit conversions, the compiler will look for a constructor of the target type that take a matching argument, and isn't flagged as explicit. If it doesn't find one, it will try to call the opImplConv on the source type that returns the target type.</p>
|
||
|
<pre>
|
||
|
class MyObj
|
||
|
{
|
||
|
double myValue;</pre><pre> // Allow MyObj to be implicitly created from double
|
||
|
MyObj(double v) { myValue = v; }</pre><pre> // Allow MyObj to be implicitly converted to double
|
||
|
double opImplConv() const { return myValue; }</pre><pre> // Allow MyObj to be created from int, but only explicitly
|
||
|
MyObj(int v) explicit { myValue = v; }</pre><pre> // Allow MyObj to be converted to int, but only explicitly
|
||
|
int opConv() const { return int(myValue); }
|
||
|
}
|
||
|
</pre><p>This should only be used for value conversions and not reference casts. That is, the methods are expected to return a new instance of the value with the new type.</p>
|
||
|
<p>If a reference cast is desired, i.e. a different type of handle to the same object instance, then the opCast method should be implemented instead. The compiler will attempt to rewrite an expression <code>cast<type>(expr)</code> as <code>expr.opCast()</code>, and chose the opCast overload that returns a handle of the desired type. Here too the opImplCast can be implemented instead if the reference cast is allowed to be performed implicitly by the compiler.</p>
|
||
|
<pre>
|
||
|
class MyObjA
|
||
|
{
|
||
|
MyObjB @objB;
|
||
|
MyObjC @objC;
|
||
|
MyObjB @opCast() { return objB; }
|
||
|
MyObjC @opImplCast() { return objC; }
|
||
|
const MyObjB @opCast() const { return objB; }
|
||
|
const MyObjC @opImplCast() const { return objC; }
|
||
|
}
|
||
|
</pre><p>An example where the opCast/opImplCast operator overloads come in handy is when extending a type without directly <a class="el" href="doc_script_class_inheritance.html">inheriting</a> from it.</p>
|
||
|
<dl class="section see"><dt>See also</dt><dd><a class="el" href="doc_expressions.html#conversion">Type conversions</a>, <a class="el" href="doc_adv_inheritappclass.html">Inheriting from application registered class</a> </dd></dl>
|
||
|
</div></div><!-- contents -->
|
||
|
</div><!-- PageDoc -->
|
||
|
</div><!-- doc-content -->
|
||
|
<!-- start footer part -->
|
||
|
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
|
||
|
<ul>
|
||
|
<li class="footer">Generated on Sat Dec 5 2020 23:20:24 for AngelScript by
|
||
|
<a href="http://www.doxygen.org/index.html">
|
||
|
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
</body>
|
||
|
</html>
|