I have a class like that (I leave only the relevant part):
template<class T>
class MyList
{
public:
// ....
typename QList<T*>::iterator begin()
{
return list.begin();
}
typename QList<T*>::iterator end()
{
return list.end();
}
typename QList<T*>::iterator skip(int n)
{
auto ite = list.begin();
while(n --> 0)
++ite;
return ite;
}
QList<T*> list;
};
when I went to use the class:
MyList<Foo*> foo;
for(Foo* f : foo.skip(1)) {
I get this error:
'begin' was not declared in this scope
I remove skip() call, the loop works fine... I don't understand why. Why that and how do I fix this?
This is just how range-based for loops work in C++. In particular, when in a range expression the participant is a class type, in your case MyList, for the expression to be legitimate the class type must have defined members begin and end.
Member function MyList::skip returns an iterator to a QList<T*>. This iterator class doesn't define any begin and end members and the compiler renders this type (i.e., the iterator) not a legitimate participant for a range-based for loop expression while the class type MyList that has defined members begin and end renders legitimate.
More info on how a range-for loop works you can find here.
Related
Say I have two structs that define a linked list:
....
....
type node struct {
item interface{}
next *node
}
type LinkedList struct {
first *node
N int
}
...
...
and I want to compare the value of the type of the underlying node, say, in a find function where we check if k == node.item such that:
func (l *LinkedList) find (key interface{}) bool {
result := false
if !l.isEmpty() {
for x:= l.first; x != nil; x = x.next {
if x.item == key {
result = true
break
}
}
return result
}
this will not work for the expected find function because the underlying types are different, hence the func will always return false. We can confirm this upon reflecting the type:
fmt.Println(reflect.TypeOf(key), reflect.TypeOf(x.item))
>>> string, *main.node
Tried workarounds?
I've tried asserting the type but alas this does not work and panics
tmp := x.item.(string)
>>>panic: interface conversion: interface {} is *main.node, not string
This case is the same for using fmt.Sprintf(x.item)
I'm a bit stumped as to where to go from here. Is there a way to do this?
Inserting item to linked list
The following snippet should clarify how insertion is handled
func (l *LinkedList) insertFirst(item interface{}) {
var first *node = new(node)
oldfirst := l.first
first.item = item
first.next = oldfirst
l.first = first
l.N++
}
.....
//which gets called somewhere like
var n *node = new(node)
n.item = item
l.insertFirst(n)
.....wait no theres the error!
----------
burak-serdar you are 100% correct that I am inserting the node in the node!
The interface comparison in find() is a valid comparison and it will work if the type of the key and the type of the value stored in the node are the same. However, evidence points to you adding a node in place of a value.
I want to declare a parameter type as Maybe a function with a default value of undefined.
However I am getting Flow errors as neither undefined or null are considered to be of type function.
Is there are way to do this?
This is how I would implement a function that executes a given function, unless the given function is undefined:
function maybeExecute<A: *, R>(f: ?(...args: A) => R, ...args: A): ?R {
if (f) {
return f(...args)
}
}
That type-checks in Flow v0.64.0. The use of the ? indicates that f might be undefined or null. The if (f) { /* ... */ } check narrows the type of f so that inside the body of the if Flow can guarantee that f is a function.
You can get a little fancier and declare multiple signatures to make maybeExecute an overloaded function like this:
declare function maybeExecute<A: *, R>(f: (...args: A) => R, ...args: A): R
declare function maybeExecute(f: null | void, ...args: mixed[]): void
function maybeExecute(f, ...args) {
if (f) {
return f(...args)
}
}
With the overloaded version if Flow is able to infer that the given function was defined then it may be able to infer that the return value of maybeExecute is also defined.
This is how you annotate a variable / constant as holding a function of a particular type:
declare type TFunction = () => any;
const foo: TFunction = function foo() {};
What is the syntax when one declares a function:
function boo() {}
?
There's no way to put: TFunction on your function boo() declaration. However, you can flow check it by writing the no-op statement (boo: TFunction); afterward. The only drawback is this evaluates boo at runtime.
Probably the best way to do it though is to not worry about explicitly declaring that boo is a TFunction, and instead just rely on Flow to check it any time you use boo where a TFunction is expected.
Here's a more concrete example of what I mean: (Try flow link)
/* #flow */
type ArithmeticOperation = (a: number, b: number) => number;
function add(a: number, b: number): number {
return a + b;
}
function concat(a: string, b: string): string {
return a + b;
}
function fold(array: Array<number>, operation: ArithmeticOperation): number {
return array.reduce(operation);
}
fold([1, 2, 3], add); // ok because add matches ArithmeticOperation
fold([1, 2, 3], concat); // flow error because concat doesn't match
Coming late to this question, but if you are talking about declarations in the sense of "compile-time declarations, separate from code, that use the declare keyword", then per the Flow declarations docs, you should be able to declare globals like this:
declare var boo: TFunction;
or scoped items as members of their containing module or type:
declare class FunctionHolder {
boo: TFunction;
}
In an object, I have an array of const-handles to some object of another specific class. In a method, I may want to return one of this handles as an inout-parameter. Here as a simplified example:
class A {}
class B {
const(A) a[];
this() {
a = [new A(), new A(), new A()];
}
void assign_const(const(A)* value) const {
// *value = a[0]; // fails with: Error: cannot modify const expression *value
}
}
void main() {
const(A) a;
B b = new B();
b.assign_const(&a);
assert(a == b.a[0]); // fails .. obviously
}
I do not want to remove the const in the original array. Class B is meant as some kind of view onto a collection constant A-items. I'm new to D coming from C++. Do I have messed up with const-correctness in the D-way? I've tried several ways to get this to work but have no clue how to get it right.
How is the correct way to perform this lookup without "evil" casting?
Casting away const and modifying an element is undefined behavior in D. Don't do it. Once something is const, it's const. If the element of an array is const, then it can't be changed. So, if you have const(A)[], then you can append elements to the array (since it's the elements that are const, not the array itself), but you can't alter any of the elements in the array. It's the same with immutable. For instance, string is an alias for immutable(char)[], which is why you can append to a string, but you can't alter any of its elements.
If you want an array of const objects where you can alter the elements in the array, you need another level of indirection. In the case of structs, you could use a pointer:
const(S)*[] arr;
but that won't work with classes, because if C is a class, then C* points to a reference to a class object, not to the object itself. For classes, you need to do
Rebindable!(const C) arr;
Rebindable is in std.typecons.
I'm wrapping a C++ framework with boost::python and I need to make a C++ method overrideable in python. This is a hook method, which is needed by the framework and has a default implementation in C++, which iterates through a list (passed as parameter) and performs a choice. The problems arise because the choice is stated by returning a pointer to the chosen element (an iterator, in fact), but I can't find a way to return a C++ pointer as a result of a python function. Can anyone help?
Thanks
This is most certainly doable, but you don't really have enough details. What you really need to do is create a c++ function that calls your python function, proceses the python result and returns a c++ result. To paraphrase (let's assume I have a boost object called func that points to some python function that parses a string and returns an int):
using boost::python;
A* test(const std::string &foo) {
object module = import("mymodule");
object func = module.attr("myfunc");
// alternatively, you could set the function by passing it as an argument
// to a c++ function that you have wrapped
object result = func(foo);
int val = extract<int>(result);
return new A(val); // Assumes that you've wrapped A.
}
// file: https://github.com/layzerar/box2d-py/blob/master/python/world.cpp
struct b2ContactFilter_W: b2ContactFilter, wrapper<b2ContactFilter>
{
bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
override func = this->get_override("ShouldCollide");
if (func)
{
return func(ref(fixtureA), ref(fixtureB)); //ref is boost::ref
}
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
bool ShouldCollideDefault(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
return b2ContactFilter::ShouldCollide(fixtureA, fixtureB);
}
};
class_<b2ContactFilter_W, boost::noncopyable>("b2ContactFilter")
.def("ShouldCollide", &b2ContactFilter::ShouldCollide, &b2ContactFilter_W::ShouldCollideDefault)
;
Is this what you need ?