You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
I would like to hear your opinion on this code:
As you can see, I did a cast on the constant variable, so it is required to match the third template. - But, if I dont cast the variable, the compiler cannot select a matching template, and complains about ambiguous call. - But shouldnt this also be the case for the non-const call one line above??
Why does the compiler select the non-reference call for the non-const variable, instead of the reference-call. - And, why does the const variable not match as the non-const variable.
This is (I am quite confident now) obviously an inconsistent behaviour, especially, because it works for pointer, objcets and structs exactly as expected. - I make my claim, this is a bug in the compilers template matching algorithm.
What do you think?
EDIT:
And to proove my point further, if you change the first template like this, and change the call to the __func() as shown below, the compiler suddenly switches over to have issues with the non-const variable. The behaviour now is vice-versa between "int" and "const int".
If you remove the cast operation within the function call, the compiler will complain again. - And it is vice-versa with the const declarations. - The compilers matching for "const" and "non-const" is mixed up.
Well I think you will not like my conclusions
Short version :
__func(target_int, 7); __func(target_int, _int); __func(target_int, (int)_int); __func(target_int, c_int); __func(target_int, (const int)c_int);
If we take all these variants, with const templates none of them should compile and all should be ambiguous.
At least the last 4. As in MQL a literal can't be passed to a const by reference (which should be possible like in it's in C++, that would be useful).
So I do agree with you there is an inconsistent behaviour, but not where you think it is, the consistent behaviour would be to reject all. It's by design of MQ developers.
Longer version :
The origin of the issue is the usage of a template by value and one by reference with the same types. How would you choose between the by value and the by ref version ? You can try it in C++, it doesn't work either.
With non-const template, it's a bit different. Like in c++ the explicit cast will work to disambiguated the template to use, because (const int) or (int) casts will call the by value version. You can't use (const int &) and (int &) casts to pick the "by reference" version because again it leads to ambiguity (and anyway this is not valid in MQL). So only 2 of the 5 call are ambiguous.
Here is the C++ code :
Which gives :
(Again the site removed all <CR><LF> from the log I posted, so I decided to use a picture).
The source type is always int. Which is perfectly understandable as the const is explicit in the template. You can read about "Template argument deduction in C++".
So MQL, is actually less restrictive than C++, it allows you to use an explicit cast and pick the by value in priority without a cast. These are design choices in my opinion, not bugs. If you want them to "fix" or change something, it will lead to more issues with what you want to do.
As a last conclusion MQL is not C++, the developers make some design choices, these are not bugs (well it would need to confirm there are real choice and not done "by chance"). I am not sure asking them to change those choices would work neither if it's desirable.
Example of design choice :
This is (I am quite confident now) obviously an inconsistent behaviour, especially, because it works for pointer, objects and structs exactly as expected.
Yes because there is no ambiguity with pointers (template 2 is used), and because objects and structs can NOT be passed by value, so template 3 is irrelevant.
I continued to work on a solution, and here it is:
Compiles and works as expected.... - Its demo-code and its functionality is not the point here, its about the type and type casting as well as the possibility to formulate "universal" code for having one function name called with any given datatype, which this code has achieved.
Still, this is not the way the keyword "const" should work. - I am sure, this is an implementation error.
Maybe someone could give some insigt on how this could be explained, or any other point of view, because, maybe my interpretation is wrong.
This is coherent with my previous post and analysis. We can deduce some additional design choices made for MQL :
* If there are 2 "by reference" template versions, the non-const version will be used.
This line :
test_int_tpl.__func(target_int, _int); // Is using this version void __func(USER_DATA& p_out, USER_DATA& p_in)
* The non-template version(s) has priority over template version(s). (The above is not ambiguous with template versions).
* If there 2 matching versions, one using const-correctness, the other one will be used.
This line :
EDIT:
There is something incoherent or which I missed the logic behind it.
In the previous version of Dominik code :
While in last code version :
So the logic seems reversed and didn't lead to an ambiguity. The only difference is the first code is non member template functions, while the last is class member template functions.
That could be a bug.
This is coherent with my previous post and analysis. We can deduce some additional design choices made for MQL :
* If there are 2 "by reference" template versions, the non-const version will be used.
This line :
* The non-template version(s) has priority over template version(s). (The above is not ambiguous with template versions).
* If there 2 matching versions, one using const-correctness, the other one will be used.
This line :
EDIT:
There is something incoherent or which I missed the logic behind it.
In the previous version of Dominik code :
While in last code version :
So the logic seems reversed and didn't lead to an ambiguity. The only difference is the first code is non member template functions, while the last is class member template functions.
That could be a bug.
I see... - You really took your time to dig into this, thank you for the effort and obviously you fond something, I didnt see.
Aside from C/C++, lets try to stick with MQL5 compiler for this, although its a good reference.
I tried to point out following, and maybe I am mistaking this for an error. I somehow seem to not get my head around it.
Following code does not compile, but the errors seem to lead me to where the twist (I am presuming) is having its effect. - I assume its due to the fact, const gets dropped, but is it correct to drop it in this regard, as classes, pointers and structs do not drop it when expanding a template. -
I have removed all const keywords just to be sure, we are not mixing in anything.
And in comparison this code:
Please note the difference in the function signatures.
First version;
will give compile error
referring to this function call:
And when I change the function signature to this:
I get following error:
referring to this call:
I dont think this is intended behaviour, or what the hell am I missing here???
At least, shouldnt it be exactly the other way around?
But here comes the twist:
With these signatures:
This function call:
will match to this function:
While when I use these signatures:
This function call:
will match this function:
In conclusion, this means, if I understand this right, in the first case, the const reference declared signature does not match. - becuase it is const. and we are passing in a non-cosnt variable, so the non-const signature is preferred.
In the second case, where the function signature has no const directives, and when passing in a const argument, the const directive is not being dropped while expanding the template, thus both templates, (CALL_TYPE x) and (const CALL_TYPE& x) would match. because (CALL_TYPE x) is expanded to (const CALL_TYPE x)
In the other case, with the signatures being (CALL_TYPE x) and (CALL_TYPE& x), both without const directive, when expanding with a non-const variable would expand to (int x) and (int& x).
But shouldnt they also expand to (const CALL_TYPE x) and (const CALLTYPE& x) for the const variable to be this: (const int x) and (const int& x) ... - Shouldnt this be as well ambiguous?
And if so, then shouldnt it be possible to declare a template with and without const, providing a match for both cases like this:
Well, this does not work for following reason:
But why can I create a matching template like this:
And now I get the correct error:
Both calls now are ambiguous:
My current conclusion is, its probably easier to exploit this "inconsistency" than to get it fixed, although I personally would like to see it being fixed, enabling the compiler to select the most likely possible match, preferring the reference type nad falling back to the value type, if references are not matching.
EDIT:
Maximum confusion at the moment.....
Why is the compiler not complaining about __func(), but only about __call()...
These three function calls
test_int_tpl.__func(target_int, 7); test_int_tpl.__func(target_int, _int); test_int_tpl.__func(target_int, c_int);
Should match following templates:
Which they do.
But if that is the case, why dont these function calls
Match these templates:
And why is the call to __func() not ambiguous???
EDIT 2:
And why isnt this template overriding:
While this is:
And this is not:
Something strange is going on here
Well it's hard to answer to such a long post, probably the longest I have ever seen on this forum
You should have cut it in several posts.
And I am getting confused again.
Well it's hard to answer to such a long post, probably the longest I have ever seen on this forum
You should have cut it in several posts.
And I am getting confused again.
Well, i suggest to just focus on the EDIT and EDIT2 part of the post....
I could have split it up... - Its a complicated issue and its not that easy to understand (for me).
Well, i suggest to just focus on the EDIT and EDIT2 part of the post....
I could have split it up... - Its a complicated issue and its not that easy to understand (for me).
No worries it's complicated for me as well, there is no standard behaviour to compare it due to the difference with C++.
I am trying to deduce a logic from analysis of the results, and we will see step by step if this logic continue to match until the end, or if there are some incoherences. The final goal is to either find something wrong in the logic, if the MQ choices are by design (on purpose) or by "chance" (random). And if there are obvious bugs.
I am still trying to find a logic about your first comparison which is not obvious. Yesterday I missed it, because I was using 3 versions of the template, ref, const ref, and value. Then both int and const it are ambiguous, all ok so I didn't check further.
I see... - You really took your time to dig into this, thank you for the effort and obviously you fond something, I didnt see.
At least, shouldnt it be exactly the other way around?
Work in progress...
Let see your first comparison.
test_int_tpl.__call(_int);
test_int_tpl.__call(c_int);
Thank you to push me to dig into this. It's very useful.
Work in progress...
Let see your first comparison.
...
EDIT:
There is something incoherent or which I missed the logic behind it.
In the previous version of Dominik code :
While in last code version :
So the logic seems reversed and didn't lead to an ambiguity. The only difference is the first code is non member template functions, while the last is class member template functions.
That could be a bug.
This is not a bug and is coherent, the difference is because the __call template selected is also depending of the choice of __func used, and the selected __func is a non templated with "const USER_DATA& p_in". So this specific case is clear.
Thank you to push me to dig into this. It's very useful.
Work in progress...
Let see your first comparison.
...
I continued the analysis of your long post, with this " But here comes the twist: ... "
This isn't something different from the first comparison, same issue. So my post #37 is already synthetizing it.
Next one :
And if so, then shouldnt it be possible to declare a template with and without const, providing a match for both cases like this:
This is perfectly logic, this is not allowed at all, because it makes no sense, it's exactly the same, and the const is superfluous.
Then :
But why can I create a matching template like this:
Both calls now are ambiguous: ...
Yes this is perfectly clear (to me at least ).
So we come to your first EDIT:
Why is the compiler not complaining about __func(), but only about __call()...
But if that is the case, why dont these function calls
Match these templates:Because the choice of templates is not the same. You have there 3 template versions for __Call which are also using __func, while for the __func() you have 1 non-template and 2 templates. That leads to the difference.
To terminate, I just don't understand your EDIT 2. It's unclear in what context you are talking.
So all in all, from my point of view, my post #37 is well summarizing the main issue. We need to get an explanation about it and don't waste more time until we have one. Everything else follows from there.