Jump to page: 1 2
Thread overview
How to turn this C++ into D?
Nov 05, 2014
Patrick Jeeves
Nov 05, 2014
luminousone
Nov 06, 2014
thedeemon
Nov 05, 2014
Ali Çehreli
Nov 05, 2014
Ali Çehreli
Nov 05, 2014
Adam D. Ruppe
Nov 05, 2014
Ali Çehreli
Nov 05, 2014
luminousone
Nov 05, 2014
Patrick Jeeves
Nov 05, 2014
luminousone
Nov 05, 2014
Patrick Jeeves
Nov 05, 2014
luminousone
November 05, 2014
So this is more a stackoverflow question, but I feel like later searchers will be more likely to find it if I put it here.

if I have the following C++ code:

class foo
{
static std::list<foo*> foo_list;
typedef std::list<foo*>::iterator iterator;
public:
    foo()
    {
       foo_list.push_back(this);
    }
    ~foo()
    {
       foo_list.remove(this);
    }

    static void DO_TASK()
    {
        for(iterator i = foo_list.begin(); i < foo_list.end(); ++i)
        {
            (*i)->process();
        }

        for(iterator i = foo_list.begin(); i < foo_list.end(); ++i)
        {
            (*i)->advance();
        }
    }

    virtual void process() = 0;
    virtual void advance() = 0;
}

How can I turn this into D?  Is there a way to register that static list with the garbage collector so it doesn't look into it or anything?

Similarly, I feel like this would be an interface in D, but interfaces don't have constructors.
November 05, 2014
On Wednesday, 5 November 2014 at 17:17:11 UTC, Patrick Jeeves wrote:
> So this is more a stackoverflow question, but I feel like later searchers will be more likely to find it if I put it here.
>
> if I have the following C++ code:
>
> class foo
> {
> static std::list<foo*> foo_list;
> typedef std::list<foo*>::iterator iterator;
> public:
>     foo()
>     {
>        foo_list.push_back(this);
>     }
>     ~foo()
>     {
>        foo_list.remove(this);
>     }
>
>     static void DO_TASK()
>     {
>         for(iterator i = foo_list.begin(); i < foo_list.end(); ++i)
>         {
>             (*i)->process();
>         }
>
>         for(iterator i = foo_list.begin(); i < foo_list.end(); ++i)
>         {
>             (*i)->advance();
>         }
>     }
>
>     virtual void process() = 0;
>     virtual void advance() = 0;
> }
>
> How can I turn this into D?  Is there a way to register that static list with the garbage collector so it doesn't look into it or anything?
>
> Similarly, I feel like this would be an interface in D, but interfaces don't have constructors.

abstract class foo {
    static DList!foo foo_list;
    this() {
        if( foo_list is null )
            foo_list = make!(DList!foo);
        foo_list.insert(this);
    }
    ~this(){ foo_list.remove(this); }
    static void DO_TASK() {
        foreach( i ; foo_list ) { i.process(); }
        foreach( i ; foo_list ) { i.advance(); }
    }
    abstract void process();
    abstract void advance();
}

note that static is thread local in D, so foo_list would be unique per thread, if you want it globally unique then you need to pull it out of the class and market it

__gshared foo_list;

Also no need to mark functions as virtual, as dlang is currently virtual by default rather then final by default, for best optimization be sure to mark functions as final when possible.
November 05, 2014
On 11/05/2014 09:17 AM, Patrick Jeeves wrote:

> class foo
> {
> static std::list<foo*> foo_list;
> typedef std::list<foo*>::iterator iterator;
> public:
>      foo()
>      {
>         foo_list.push_back(this);
>      }
>      ~foo()
>      {
>         foo_list.remove(this);
>      }

Going completely off-topic, I recommend against objects registering themselves that way. That idiom has caused trouble in more than one project for us.

In general, I think a constructor should not have side-effects unless needed for the object's construction (e.g. allocating a resource for the object should obviously fine).

Ali

November 05, 2014
On 11/05/2014 10:07 AM, Ali Çehreli wrote:

> On 11/05/2014 09:17 AM, Patrick Jeeves wrote:
>
>  > class foo
>  > {
>  > static std::list<foo*> foo_list;
>  > typedef std::list<foo*>::iterator iterator;
>  > public:
>  >      foo()
>  >      {
>  >         foo_list.push_back(this);
>  >      }

Argh! I forgot to add an important, perhaps philosophical, point. :) Continuing the off-topic, an object should be considered constructed only after hitting that closing curly bracket above. If so, then that push_back would be adding an incomplete object to the list.

Ali

November 05, 2014
On Wednesday, 5 November 2014 at 18:10:38 UTC, Ali Çehreli wrote:
> If so, then that push_back would be adding an incomplete object to the list.

scope(success)?


But the D translation worries me too because the destructor won't run at the same time as the C++ version, unless you make it a scope class or something.
November 05, 2014
On 11/05/2014 10:12 AM, Adam D. Ruppe wrote:

> On Wednesday, 5 November 2014 at 18:10:38 UTC, Ali Çehreli wrote:
>> If so, then that push_back would be adding an incomplete object to the
>> list.
>
> scope(success)?

I really like that! :)

But still not for this case because in addition to the problem with the destruction order, I would like to feel free to remove unused objects like the following without worrying about side-effects:

// C++ code
void bar()
{
    Foo seemingly_unused_here();
    // ...
}

Ali

November 05, 2014
On Wednesday, 5 November 2014 at 18:18:18 UTC, Ali Çehreli wrote:
> On 11/05/2014 10:12 AM, Adam D. Ruppe wrote:
>
> > On Wednesday, 5 November 2014 at 18:10:38 UTC, Ali Çehreli
> wrote:
> >> If so, then that push_back would be adding an incomplete
> object to the
> >> list.
> >
> > scope(success)?
>
> I really like that! :)
>
> But still not for this case because in addition to the problem with the destruction order, I would like to feel free to remove unused objects like the following without worrying about side-effects:
>
> // C++ code
> void bar()
> {
>     Foo seemingly_unused_here();
>     // ...
> }
>
> Ali

unless delete is explicitly called, I don't believe the destructor would ever be called, it would still have a reference in the static foo_list object that would stop it from being collected by the gc.

I could see the constructor situation being a problem in threaded code as well, tho it may be bad practice, I don't believe the insert(this) would actually break anything.

The scope(success) is a good idea either way however.
November 05, 2014
On Wednesday, 5 November 2014 at 18:56:08 UTC, luminousone wrote:
> unless delete is explicitly called, I don't believe the destructor would ever be called, it would still have a reference in the static foo_list object that would stop it from being collected by the gc.

This is exactly why I asked about it, and even if delete is explicitly called-- which i believe is deprecated, wouldn't the runtime fill the space with the default construtor until the GC decides to remove it? meaning it would be immediatly added back into the list?
November 05, 2014
On Wednesday, 5 November 2014 at 19:05:32 UTC, Patrick Jeeves wrote:
> On Wednesday, 5 November 2014 at 18:56:08 UTC, luminousone wrote:
>> unless delete is explicitly called, I don't believe the destructor would ever be called, it would still have a reference in the static foo_list object that would stop it from being collected by the gc.
>
> This is exactly why I asked about it, and even if delete is explicitly called-- which i believe is deprecated, wouldn't the runtime fill the space with the default construtor until the GC decides to remove it? meaning it would be immediatly added back into the list?

I don't believe that the default constructor is called. I am pretty sure delete immediately deallocates the object, deregistering its memory from the gc.

In fact I am 99% sure no constructor is called after delete, it would cause problems for objects with no default constructor, or for system related stuff done in constructors, and I haven't seen anything like that in my X11 work in d.

November 05, 2014
On Wednesday, 5 November 2014 at 19:44:57 UTC, luminousone wrote:
> On Wednesday, 5 November 2014 at 19:05:32 UTC, Patrick Jeeves wrote:
>> On Wednesday, 5 November 2014 at 18:56:08 UTC, luminousone wrote:
>>> unless delete is explicitly called, I don't believe the destructor would ever be called, it would still have a reference in the static foo_list object that would stop it from being collected by the gc.
>>
>> This is exactly why I asked about it, and even if delete is explicitly called-- which i believe is deprecated, wouldn't the runtime fill the space with the default construtor until the GC decides to remove it? meaning it would be immediatly added back into the list?
>
> I don't believe that the default constructor is called. I am pretty sure delete immediately deallocates the object, deregistering its memory from the gc.
>
> In fact I am 99% sure no constructor is called after delete, it would cause problems for objects with no default constructor, or for system related stuff done in constructors, and I haven't seen anything like that in my X11 work in d.

I guess I got confused by something... I don't know.  But what I'd really like is for it to be garbage colleceted when no references outside of that static array exist, as i mentioned at the bottom of my first post.  I illustrated my example with that specific class because when i looked up "weak pointers" on the site I found discussions getting caught up with how to avoid dangling pointers when weak pointers are used; and I wanted to illustrate that that's a non-issue in this case, because I wasn't sure how much that contributed to the solutions given.

I suppose it doesn't matter because this is based on something I do with multiple inheritance in C++, I felt like I may be able to get it to work in D because the only public members of those classes were always pure virtual functions.

As an aside, how does scope(success) work in the context of a constructor? given:

abstract class foo
{
    this()
    {
       scope(success) onAdd();
    }
    ~this()
    {
       onRemove();
    }

    onAdd();
    onRemove();
}

class bar : foo
{
    int _a;

    this(int a)
    {
       _a = a;
    }

    void onAdd()    { writeln(_a); }
    void onRemove() { writeln(_a); }
}

is _a defined as anything in either of writes? or would it be called at the wrong time relative to setting _a?
« First   ‹ Prev
1 2