Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c++ > #512

Re: Towards an object class for C++

From Daniel Krügler<daniel.kruegler@googlemail.com>
Newsgroups comp.std.c++
Subject Re: Towards an object class for C++
Date 2012-05-04 11:23 -0700
Organization A noiseless patient Spider
Message-ID <jnv18p$dqf$1@dont-email.me> (permalink)
References <18698075.117.1335982910981.JavaMail.geo-discussion-forums@pbfk7>

Show all headers | View raw


Am 02.05.2012 20:46, schrieb german diago:
>  I would like to put here, in order to be discussed, what I think it's
>  still a missing point in the C++ standard library.
>
>  I'm trying to implement an object class for c++, like C# and java
>  have, but adapted to the c++ needs. My class is targeted at c++11 (not
>  c++03 for now). The main goals I want to achieve are:
>
>  1.- Plays well with all kind of c++ types as much as possible.
>  2.- It feels comfortable and high level when used, looks as a high-level type.
>  3.- It's safe to use, no segfaults or whatever. Use of exceptions.
>
>  For my implementation, I've already decided (although not set in stone):
>
>     - Use type erasure. Client types don't need to derive from any class
>  to use object class.
>     - Value semantics. Should be used by value, not by pointer.
>     - Value type requirements: at least movable type.

 From what you show so far, you Object wrapper is some fancy unique_ptr,
thus the wrapper can only moved, never copied (cloned). While this is
often right, for other use-cases different strategies this might be a
bit limited, either cloning or shared-pointer-like semantics often is
preferred.

>     - Able to hold both polymorphic and non-polymorphic types without
>  the held types losing polymorphism.

I assume that only applies to the sliced object that is has been wrapped
by moving into the wrapper, right? I guess that you do not realize full
polymorphism for wrapped *pointers*, for example?

>     - Convertible to string.

Just out of interest: What is your suggested "canonical" to_string form
for a type that has no operator<<  useable for an std::ostream object?
I'm asking, because this is the "usual" problem for types like
dynamic_any. Java's analogue expressed as

std::string(typeid(T).name()) + '@' + boost::lexical_cast<std::string>(&t)

is what I decided for, but I'm curious for your decision.

>  Planned:
>     - Serializable.
>     - Equality comparable.

In this case, you also need a fall-back for lacking operator==. Will
this be address-identity? I think, this *can* be problematic for an
otherwise value-like type (I decided for not providing it for this reason)

>     - Hashable (to be useful in containers).
>     - Assignable to concrete types (like POCO DynamicAny class
>  http://pocoproject.org/docs/Poco.DynamicAny.html).

I would be interested in your approach for the conversion. My current
guess is that it works "roughly" for conversions to arithmetic types,
presumably based via some emulated conversion to long double (for
example) but I don't see how this can be done for general conversions,
including from class type A to class type B.

>  I'm facing one very concrete problem:
>
>    - I want that function getReference() from object can cast an object
>  to its concrete type or, if polymorphic, to any of its base classes.
>  When the held value in object is not polymorphic, it's easy, but when
>  you want to hold a polymorphic type and be able to cast to a base
>  class, things get more complicated.

An often found technique is one where you would specialize ObjectModel
depending on whether it is a class type or not. If it is a class type,
you would change its specialization to

template<class T>
class ObjectModel : public T, ObjectInterface { [..] };

which works for all except final classes. To prevent unintentional
overriding of ObjectInterface's functions by those of T, one possible
trick is that you invent an empty tag interface, like

struct nested_object {
   virtual ~nested_object() {}
};

and derive

template<class T>
class nested_class : public T, nested_object { };

You need to have a single function within your type-erased wrapper that
returns a nested_object*. You need to ensure that it will return nullptr
for non-class types, otherwise you can perform the dynamic cast to any
type starting from nested_object*.

Other techniques are possible, where nested_class is not necessarily
empty (Like ObjectModel above). In this case you can prevent any
unintended overriding by introducing a unique signature type

struct unique_signature {};

and use this in all function of the wrapper.

In my own dynamic_any I used the first approach and I could easily
realize some form of reduced dynamic casts (I still think, it is
reduced, because I only perform this to actual classes, not to pointers
or references of classes.)

HTH&  Greetings from Bremen,

Daniel Krügler


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

Back to comp.std.c++ | Previous | NextPrevious in thread | Find similar


Thread

Towards an object class for C++ german diago <germandiago@gmail.com> - 2012-05-02 11:46 -0700
  Re: Towards an object class for C++ Daniel Krügler<daniel.kruegler@googlemail.com> - 2012-05-04 11:23 -0700

csiph-web