=head1 NAME

XS::Framework::Manual::recipe03 - XS::Framework basics

=cut

=head1 DESCRIPTION

Let's assume that there in an external C++ class which follows singleton
pattern. Also, let's assume that it returns C<const> singleton, i.e. all
methods of C++ class are marked as C<const>. Here is an example of such
class

    struct TimezoneRecipe03 {
        const char* get_name() const { return name; }
        static const TimezoneRecipe03& get_instance() {
            static TimezoneRecipe03* instance = new TimezoneRecipe03();
            return *instance;
        }
    private:
        TimezoneRecipe03() { name = "Europe/Minsk"; }
        const char* name;
    };


It is possible to specialize typemaps with I<const typemap>. Althought,
Perl does not have notion of const objects, it has notion of read-only
SV*, so invoking non-const method on read-only SV* wrapper leads
to C<cannot modify read-only object> error. Here is an example of typemap

    namespace xs {
        template <>
        struct Typemap<const TimezoneRecipe03*> : TypemapObject<const TimezoneRecipe03*, const TimezoneRecipe03*, ObjectTypeForeignPtr, ObjectStorageIV, StaticCast> {
            //              (1)                                         (2)                             (3)                 (4)                 (5)
            static std::string package () { return "MyTest::Cookbook::TimezoneRecipe03"; }
        };
    }


Here (1 .. 3) shows how to define typemap for const object. Please, not that
non-const typemap is auto-deduced from const typemap.

As the perl side does not owns the pointer, and, hence, does not need to
C<delete> it, we can use C<ObjectTypeForeignPtr> lifetime policy (4) and
C<ObjectStorageIV> storage policy (5). There is no leak in missing
C<DESTROY> method in xs-adapter below. Please note, that it is assumed that
no further class extension is possible (see limitations of C<ObjectStorageIV>
storage policy).

The xs-adapter code should look like:

    MODULE = MyTest                PACKAGE = MyTest::Cookbook::TimezoneRecipe03
    PROTOTYPES: DISABLE

    const char* TimezoneRecipe03::get_name() : const;
    #                                        (5) (6)

    const TimezoneRecipe03* get_instance() { RETVAL = &TimezoneRecipe03::get_instance(); }
    # (7)

It is rather trivial; hovewer, please, pay attention to a few nuances: the
C<const> methods should be marked as attribute C<const> (6) after colon (5).
The returned pointer (7) should also be marked with C<const>.