Shouldn't the two set types be identical?
#include <array>
#include <set>
#include <iostream>
template <class Iter>
std::set(Iter, Iter) -> std::set<typename std::iterator_traits<Iter>::value_type>;
int main() {
std::array a {1,2,3,4};
std::set<int> si {a.begin(), a.end()};
std::set s {a.begin(), a.end()};
for(auto& i: si) { std::cout << i << "\n"; }
for(auto& i: s ) { std::cout << i << "\n"; }
}
instead it yields:
1
2
3
4
0x7ffdf5bc9050
0x7ffdf5bc9060
even tried with additional Allocator :-(
There are two points of confusion here.
First, deduction guides must be in the scope of the class template that they're guiding, so this guide will just never be considered:
template <class Iter>
std::set(Iter, Iter) -> std::set<typename std::iterator_traits<Iter>::value_type>;
It would have to look like this:
namespace std {
template <class Iter>
set(Iter, Iter) -> set<typename iterator_traits<Iter>::value_type>;
}
But you're not allowed to add things into namespace std, so don't do that. And besides, this deduction guide already exists for set:
template<class InputIt,
class Comp = std::less<typename std::iterator_traits<InputIt>::value_type>,
class Alloc = std::allocator<typename std::iterator_traits<InputIt>::value_type>>
set(InputIt, InputIt, Comp = Comp(), Alloc = Alloc())
-> set<typename std::iterator_traits<InputIt>::value_type, Comp, Alloc>;
So there's no reason to add your version anyway.
The reason that deduction guide isn't used, nor would yours be if you put it in the right namespace, is the usual major caveat for list-initialization:
If there is a matching initializer_list<T> constructor, it is strongly preferred to anything else.
The specific language rule is that we do overload resolution specifically for those constructors first, and then we do the rest. And one of the other deduction guides in our list is:
template<class Key, class Comp = std::less<Key>, class Alloc = std::allocator<Key>>
set(std::initializer_list<Key>, Comp = Comp(), Alloc = Alloc())
-> set<Key, Comp, Alloc>;
Note that:
std::set s{a.begin(), a.end()};
is the exact same kind of construction as:
std::set u{1, 2};
Just because our two elements of the same type are iterators, doesn't mean they get treated any differently from any other two elements of the same type. So we get a set of iterators.
If you want to use the other deduction guide with the other constructor, you must use parentheses:
std::set s(a.begin(), a.end());
And remove your deduction guide!
std::set provides a constructor which takes a std::initializer_list and is able to do the type deduction of T for std::set<T>. In this case, using the syntax std::set x{a.begin(), a.end() }; will use the initializer list constructor and deduces T from that. No user defined deduction guide takes place!
If you create your object with std::set x(a.begin(), a.end()); the initilizer list constructor will not be used. Now, as no other constructor matches, deduction guides take place!
Example how the effect is if you have initializer list constructors in your code:
template < typename U >
struct X
{
// Directly makes the type deducable, because U can be deduced from the parameter of the constructor
X( std::initializer_list<U> )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template < typename ... T>
X( T... )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct ONE {};
template < typename Iter >
X( const Iter&, const Iter& ) -> X<ONE>;
template < typename U >
struct Y
{
// type U can NOT deduced from the parameter!
template < typename T>
Y( std::initializer_list<T> )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
template < typename ... T>
Y( T... )
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
struct TWO {};
template < typename Iter >
Y( const Iter&, const Iter& ) -> Y<TWO>;
int main()
{
std::array a {1,2,3,4};
X x1{a.begin(), a.end()};
X x2(a.begin(), a.end());
std::cout << "###" << std::endl;
Y y1{a.begin(), a.end()};
Y y2(a.begin(), a.end());
}
That initializer list constructors are take preference over deduction guide was also new to me and answered here:
Why does using uniform initializer syntax result in different behavior to the "old" style ()?
The important new thing for me was:
[over.match.list]
[...] overload resolution selects the constructor in two phases:
Initially, the candidate functions are the initializer-list constructors ([dcl.init.list]) of the class T and the argument list
consists of the initializer list as a single argument.
[...]
For details details see the linked question!
Related
Consider the following Dart code:
class Vec2 {
num x, y;
Vec2(this.x, this.y);
Vec2 operator*(num rhs) => Vec2(x * rhs, y * rhs);
String toString() => "<$x, $y>";
}
void main() => print(Vec2(1, 2) * 3);
The output is as expected:
<3, 6>
However, this only works when the left-hand side of the expression is a Vec2 and the right-hand side is a num. In this case, I want the multiplication operator to be commutative, so I write the following extension:
extension Vec2Util on num {
Vec2 operator*(Vec2 rhs) => Vec2(rhs.x * this, rhs.y * this);
}
One might naturally expect the following code to produce identical output to the first snippet:
void main() {
num x = 3;
print("${x * Vec2(1, 2)}");
}
However, the compiler is instead reporting that The argument type 'Vec2' can't be assigned to the parameter type 'num'. It looks as though the compiler is resolving the multiplication to num operator*(num rhs) in this case and then complaining that my Vec2 can't be passed in as a num operand. Why does the compiler apparently disregard my extension? What is the correct way to create custom commutative operators like this?
You cannot do what you want.
Dart user-definable binary operators are all methods on the first operand. Doing e1 + e2 is kind-of like doing e1.+(e2) where + is the name of the method, except you can't normally call a method +.
In order to be able to do 3 * vector, you need the method to be on 3.
You can't add methods to other people's classes, not without fiddling with their source code, and int is a system class so even that is not possible.
You cannot use extension methods because extension methods do not apply when the receiver type already has an instance method with the same name.
And int defines all the operators.
(It's like, and definitely not coincidentally, that the user-definable operators were chosen from exactly what int needs. That's not new in Dart, the operators go back to C and Java.)
So, you can define an extension method on int, but you can't call it anyway, not without an override:
extension MyInt on int {
Vector operator *(Vector other) => other.scalerMultiplication(this);
}
... MyInt(3) * vector ...
That's more complication than just swapping the operands.
I need clarity on how objects are declared and assigned a definition in F#.
What's happening in this code?
let service = {
new IService with
member this.Translate(_) = raise error }
My guess is we're creating an object that will implement some interface on the fly even though there is no actual class that's backing this object. Hence, we're removing the ceremony involved with creating an object by not having to declare a separate class to use it. In this case, we're minimizing the ceremony involved for implementing a mock object that could be used within a unit test.
Is my understanding accurate?
I tried to research my question and found the specification for F# 3.0 (Section - 6.3.8 Object Expressions)
6.3.8 Object Expressions An expression of the following form is an object expression: { new ty0 args-expropt object-members interface
ty1 object-members1 … interface tyn object-membersn } In the case
of the interface declarations, the object-members are optional and are
considered empty if absent. Each set of object-members has the form:
with member-defns endopt Lexical filtering inserts simulated $end
tokens when lightweight syntax is used. Each member of an object
expression members can use the keyword member, override, or default.
The keyword member can be used even when overriding a member or
implementing an interface.
For example:
let obj1 =
{ new System.Collections.Generic.IComparer<int> with
member x.Compare(a,b) = compare (a % 7) (b % 7) }
You can get a pretty good picture of what is happening behind the scenes if you look at the generated IL using a decompiler like ILSpy. For the example involving IComparer, it generates a hidden class, which implements the interface:
internal sealed class obj1#2 : IComparer<int> {
public obj1#2() : this() { }
int IComparer<int>.System-Collections-Generic-IComparer(int x, int y) {
int num = x % 7;
int num2 = y % 7;
if (num < num2) { return -1; }
return (num > num2) ? 1 : 0;
}
}
Inside the body of the method, it then creates a new instance:
IComparer<int> obj1 = new obj1#2();
I'm playing around with Hack for a bit and tried to create a generator function using the yield keyword. The documentation states that the return type of such a function should be the Continuation interface. However, when running hh_client on the source code example of the generator function I get the following output:
./test.php:4:3,7: Invalid yield (Typing[4110])
./test.php:3:17,28: This is an object of type Continuation
./test.php:4:3,7: It is incompatible with an object of type Generator (result of function with 'yield' in the body)
This is test.php:
<?hh
function gen(): Generator<int> {
yield 1;
yield 2;
yield 3;
}
function foo(): void {
foreach (gen() as $x) {
echo $x, "\n";
}
}
foo();
Changing the result type to Generator gives even more warnings. What is the correct way of typing a generator function?
Any mention of Continuation in the docs is outdated and wrong. There's an open issue about it.
The correct type is Generator<Tk, Tv, Ts> -- there are actually three type parameters there. Here's an example of what they mean:
$r = yield $k => $v;
The type of that generator is Generator<Tk, Tv, Ts>, where Tk is the type of $k, Tv is the type of $v, and Ts is the type of $r.
For your code, this should work:
function gen(): Generator<int, int, void> {
yield 1;
yield 2;
yield 3;
}
The first int because there is implicitly an integer key; the second int because you are yielding ints, and the void since you don't care what values are sent into the generator.
I have two longish blocks of code that are identical except in various comparative statements > is switched with <, >= with <= etc. I wanted to put these in a function and use one operator or another depending on a function input.
I am coding in MQL5 but this is very similar to C++ so hopefully methods that work in this will also be useable in my case.
You can create a comparator function for each comparison you need, and then pass the right function as an argument to the longish code blocks (wrapped in a suitably defined function)
As an example, consider the following hypothetical case where a function (myFunc) receives 2 integers(a and b)
and processes them. The processing steps are similar except for the type of comparison done on the arguments. We get around the problem by providing myFunc with the right tool for comparison.
#include <iostream>
using namespace std;
bool comp1(int a, int b) {
return a > b;
}
bool comp2(int a, int b) {
return a < b;
}
void myFunc(int a, int b, bool (*myComp)(int, int)) {
bool res = myComp(a, b);
cout << "value : " << res << endl;
}
int main()
{
myFunc(1, 2, comp1); //use >
myFunc(1, 2, comp2); //use <
return 0;
}
Clearly, comp1 and comp2 are the 2 different comparators. We pass one of them to myFunc depending on the requirements (< or >).
The best thing is that your comparisons can now be as complex as you want, and myFunc is oblivious to the complexities.
Coding in MQL4 you haven't pointers to function / templates. MQL5 has templates but formal parameter types are only built-in or basic user-defined types.
You could try something like:
enum COMPARATOR
{
C_EQUAL = 0,
C_LESS = 1,
C_GREATER = -1
C_AT_MOST = 2,
C_AT_LEAST = -2,
};
bool cmp(int a, int b, COMPARATOR c)
{
switch (c)
{
case C_LESS: return a < b;
case C_AT_MOST: return a <= b;
case C_EQUAL: return a == b;
case C_AT_LEAST: return a >= b;
case C_GREATER: return a > b;
}
Alert("INTERNAL ERROR: UNKNOWN COMPARISON");
return false;
}
void a_function(COMPARATOR c)
{
if (cmp(MathRand(), 13, c))
Print("BOOM");
// *** If you need the "opposite" of c *** you can write:
if (cmp(Time[0], Time[1], COMPARATOR(-c))
Alert("DONE");
}
It isn't elegant but it's effective.
Pass in a "comparator" as a function or functor, in this case I'm using the std::less and std::greater functors defined in the functional header, there are functors defined for more or less all the operators.
#include <iostream>
#include <functional>
template<typename Comparator>
void do_something(Comparator comp)
{
int a = 1;
int b = 2;
if (comp(a, b)) {
std::cout << "expression was true" << std::endl;
} else {
std::cout << "expression was not true" << std::endl;
}
}
int main(int argc, char* argv[])
{
do_something(std::greater<int>());
do_something(std::less<int>());
}
Output:
expression was not true
expression was true
In short, I need to be able to traverse Z3_ast tree and access the data associated with its nodes. Cannot seem to find any documentation/examples on how to do that. Any pointers would be helpful.
At length, I need to parse smt2lib type formulae into Z3, make some variable to constant substitutions and then reproduce the formula in a data structure which is compatible with another unrelated SMT sovler (mistral to be specific, I don't think details about mistral are important to this question but funnily enough it does not have a command line interface where I can feed it text formulae. It just has a C API). I have figured that to generate the formula in mistral's format, I would need to traverse the Z3_ast tree and reconstruct the formula in the desired format. I cannot seem to find any documentation/examples that demonstrate how to do this. Any pointers would be helpful.
Consider using the C++ auxiliary classes defined at z3++.h. The Z3 distribution also includes an example using these classes. Here is a small code fragment that traverses a Z3 expression.
If your formulas do not contain quantifiers, then you don't even need to handle the is_quantifier() and is_var() branches.
void visit(expr const & e) {
if (e.is_app()) {
unsigned num = e.num_args();
for (unsigned i = 0; i < num; i++) {
visit(e.arg(i));
}
// do something
// Example: print the visited expression
func_decl f = e.decl();
std::cout << "application of " << f.name() << ": " << e << "\n";
}
else if (e.is_quantifier()) {
visit(e.body());
// do something
}
else {
assert(e.is_var());
// do something
}
}
void tst_visit() {
std::cout << "visit example\n";
context c;
expr x = c.int_const("x");
expr y = c.int_const("y");
expr z = c.int_const("z");
expr f = x*x - y*y >= 0;
visit(f);
}