Boost::Any ported to D

Marcin Kuszczak aarti at interia.pl
Mon Oct 2 14:23:50 PDT 2006


Bruno Medeiros wrote:

> Marcin Kuszczak wrote:
>> Bruno Medeiros wrote:
>> 
>>> Marcin Kuszczak wrote:
>>>> 3. I can not compile program after putting PlaceHolder interface and
>>>> Holder class into Any class (like in the original approach). Is it bug
>>>> or am I doing something wrong?
>>> Hum, C++ allows member(=inner) classes? Didn't know that. Are they
>>> static or "instance"(meaning they require an outer class context)
>>> classes? Recall that in D they are "instance" by default, and static on
>>> option only.
>> 
>> As I know outer class works just as namespace for inner class. So I would
>> say static class definitions.
>> 
> 
> And when you ported to D, did you make the D inner classes static too?
> 

After some more experiments it occurs that I can move Holder class into Any
class without problems. It could be putted into public or private section.
It doesn't have to have keyword static to work well.

Problems are beginning when I move interface PlaceHolder into private
section of Any. After that I get linking errors:

dmd test_any.d any.d
gcc test_any.o any.o -o test_any -m32 -lphobos -lpthread -lm -Xlinker -ldl
test_any.o: In function
`_D5doost3any3any3Any31__T6assignTC5doost3any3any3AnyZ6assignFC5doost3any3any3AnyZC5doost3any3any3Any':test_any.d
(.gnu.linkonce.t_D5doost3any3any3Any31__T6assignTC5doost3any3any3AnyZ6assignFC5doost3any3any3AnyZC5doost3any3any3Any+0x1b):
undefined reference to
`_D5doost3any3any3Any11PlaceHolder5cloneFZC5doost3any3any3Any11PlaceHolder'
any.o: In function `_D5doost3any3any3Any4typeFZC8TypeInfo':any.d
(.gnu.linkonce.t_D5doost3any3any3Any4typeFZC8TypeInfo+0x1b): undefined
reference to `_D5doost3any3any3Any11PlaceHolder4typeFZC8TypeInfo'
collect2: ld returned 1 exit status
--- errorlevel 1


What is more interesting there is no problem when I put interface into
public section of Any.

In attachment best code which works.

-- 
Regards
Marcin Kuszczak
(Aarti_pl)
--nextPart1765265.nsI9JyAznH
Content-Type: text/x-c++src; name="any.d"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="any.d"

// Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompAnying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// See http://www.boost.org/libs/Any for Documentation.
// what:  variant type boost::Any
// who:   contributed by Kevlin Henney,
//        with features contributed and bugs found by
//        Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
// when:  July 2001
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// Translation to D Programming Language
// (c) Marcin Kuszczak, 2006
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

module doost.any.any;

// -----------------------------------------------------------------------------

class Any {
public:
    this() {
        content=null;
    }

    Any assign(ValueType)(ValueType value) {
        static if (is(ValueType == Any)) content = value.content !is null ? value.content.clone() : null;
            else content=new Holder!(ValueType)(value);
        return this;
    }

    Any swap(Any rhs) {
        PlaceHolder p=content;
        content=rhs.content;
        rhs.content=p;
        return this;
    }

    bool empty() {
        return (content is null);
    }

    TypeInfo type() {
        return content !is null ? content.type() : typeid(void);
    }

    interface PlaceHolder {
        TypeInfo type();
        PlaceHolder clone();
    }

private:

    class Holder(ValueType) : PlaceHolder {
    public:
        this(ValueType value) {
            held=value;
        }

        TypeInfo type() {
            return typeid(ValueType);
        }

        PlaceHolder clone() {
            return new Holder(held);
        }

        ValueType held;
    }

    PlaceHolder content;
}

// -----------------------------------------------------------------------------

ValueType anyCast(ValueType)(Any operand) {
    if (operand is null) throw new BadAnyCast(BadAnyCast.NullOperand);
    if (operand.empty) throw new BadAnyCast(BadAnyCast.ValueNotAssigned);
    if (operand.type!=typeid(ValueType)) throw new BadAnyCast(BadAnyCast.InvalidType);

    auto p=cast(Any.Holder!(ValueType))(operand.content);
    return p.held;
}

// -----------------------------------------------------------------------------

class BadAnyCast : Exception {
public:
    enum {NullOperand, ValueNotAssigned, InvalidType};

    this(int reason) {
        char[] msg="BadAnyCast: failed conversion using anyCast";

        switch (reason) {
            case NullOperand : msg~= " - operand is null"; break;
            case ValueNotAssigned: msg~= " - value is not assigned"; break;
            case InvalidType: msg~= " - type of value is different than requested"; break;
            default: break;
        }

        super(msg);
    }

    int reason;
}

--nextPart1765265.nsI9JyAznH
Content-Type: text/x-java; name="test_any.d"
Content-Transfer-Encoding: 8Bit
Content-Disposition: attachment; filename="test_any.d"

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Example program to Any (discriminated variant container)
//
// Translation to D Programming Language
// (c) Marcin Kuszczak, 2006
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

import doost.any.any;
import std.stdio;

// -----------------------------------------------------------------------------

Any[] many;

// -----------------------------------------------------------------------------

class Test {
    char[] toString() {
        return "Test class";
    }
}

void printVector() {
    // type, empty and anyCast test

    for(uint i=0; i<many.length; i++) {
        writef("\tNo. %s; ", i);
        writef("\tType: %s; ", many[i].type);
        writef("\tEmpty: %s; ", many[i].empty);
        if (many[i].empty==false) {
            writef("\tValue: ");
            switch (many[i].type.toString) {
                case "int" : writef(anyCast!(int)(many[i])); break;
                case "double" : writef(anyCast!(double)(many[i])); break;
                case "char[]" : writef(anyCast!(char[])(many[i])); break;
                case "Test" : writef(anyCast!(Test)(many[i]).toString); break;
                case "bool" : writef(anyCast!(bool)(many[i])); break;
                case "bool*" : writef(*anyCast!(bool*)(many[i])); break;
                default: writef("Unknown type - don't know how to cast");
            }
        }
        writefln;
    }
}

// -----------------------------------------------------------------------------

void main() {

    bool assigned=false;

    //Assigning test
    writef("Assigning test");
    writefln();
    many~=(new Any).assign(5);
    many~=(new Any).assign(5.5);
    many~=(new Any).assign(cast(char[])("string test"));
    many~=(new Any).assign(new Test);
    many~=(new Any).assign(many[3]);
    many~=new Any;
    many~=(new Any).assign(many[0]);
    many~=(new Any).assign(&assigned);


    printVector();
    writefln();

    // exception handling test
    writef("Exception handling test");
    writefln();
    writef("Casting null to int: ");
    try {
        anyCast!(int)(null);
    }
    catch (BadAnyCast e) {
        writefln(e.toString);
    }

    writef("Casting empty Any to int: ");
    try {
        anyCast!(int)(many[5]);
    }
    catch (BadAnyCast e) {
        writefln(e.toString);
    }

    writef("Casting Test to char[]: ");
    try {
        anyCast!(char[])(many[3]);
    }
    catch (BadAnyCast e) {
        writefln(e.toString);
    }

    writefln();

    // swaping test
    writef("Swaping test");
    writefln();
    many[0].swap(many[3]);
    many[5].swap(many[2]);
    many[7].swap(many[1]);

    bool* p;

    p=anyCast!(bool*)(many[1]);
    *p=true;

    printVector;
}


More information about the Digitalmars-d-announce mailing list