1

I'm trying to create an object which de facto is analogue of Python's list object. In my code I have the following classes: object_type, type_type, none_type, bool_type, int_type, float_type, bytes_type, where object_type is abstract class.

Abstract class has some virtual functions like type_type __type__(void), bytes_type __name__(void), bytes_type __repr__(void), bool_type __bool__(void), int_type __int__(void), float_type __float__(void), bytes_type __bytes__(void).

type_type class has following constructor: type_type(object_type*); during construction pointer to source object is stored to object_type* type_type::__cdata__ and is used when user wants to compare two types using type_type::__eq__(const type_type&) function (this function uses typeid as you might have been guessed).

I need to create list_type object, which can store any object which is based on object_type. It must have __get__(const int_type&) function to get an element and __set__(const int_type&, object_type*) function to set an element. All objects are stored inside std::vector<object_type*> __cdata__.

How can I force list_type::__get__(const int_type&) to return correct object? Let's imagine we have list_type, which contains three elements: [bytes_type object0, int_type object1, float_type object3]. Using list_type::__get__(0) should return bytes_type object0. Probably function type_type object_type::__type__() can be useful.

There is a diffictulty that user can create a new object_type based type during execution (all what I've described is used to create a new toy-language). However all types are based on object_type and has its virtual functions.

Do you have any ideas? I'd be glad to meet your advice.

P.S. git repository: https://github.com/ghostmansd/quirinus

ghostmansd
  • 3,285
  • 5
  • 30
  • 44

2 Answers2

1

Your method conventions you use with your methods are very python-like. As @BenjaminLindley said, this is invalid, because in C++, names prefixed with double underscores are reserved to the compiler (in Python they are reserved for special methods like __eq__, but in C++ you can overload == for similiar effect).

Note: the following works for types known at compile time.

As C++ is statically typed, you can't return multiple types. You have to return object_type& which then can be casted back to original type:

Your list can store (smart) pointers to object_type, and your get method (or an overloaded [] operator) will return reference to object_type.

// data is underlying container of pointers, getInt() returns int value from int_type
object_type& get(const int_type& i) { return *(data[i.getInt()]); }

References are used here to avoid slicing and to gain access to value stored in a list.

Users will have to cast to get the original type of the object.

try
{
    bytes_type& object0 = dynamic_cast<bytes_type&>(your_list.get(0))
    // operate on object0
}
catch(std::bad_cast& e)
{
     // type was incorrect
     std::cout << "Invalid type";
}

boost::any is similiar to this idea, so you can look how they implemented it.

milleniumbug
  • 15,379
  • 3
  • 47
  • 71
1
All objects are stored inside std::vector<object_type*> __cdata__.

How can I force list_type::__get__(const int_type&) to return correct object?

You already have the correct object inside std::vector<object_type*>. It's type is object_type*. You should return either object_type* or object_type&. These are the best return type possible. C++ type system is not sophisticated enough to have function's return type depend on its input.

You should consider working with smart pointers instead of raw pointers though, but the principle stays the same.

A side note. What can you do with a reference or pointer (smart or raw) to object_type? Two things: you can cast it to some other pointer or reference, or you can call a virtual function through it. Casting is only useful if you know or can guess the target type, and implementing every imaginable operation through a virtual function is not practical since there's an infinite set of imaginable operations. This possibly means that this design is not the best one for what you want to do.

Oh, and you should not use double underscores in C++.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243