NAME
    Class::XSConstructor - a super-fast constructor in XS

SYNOPSIS
      package Person {
        use Class::XSConstructor qw( name! age email phone );
        use Class::XSAccessor {
          accessors         => [qw( name age email phone )],
          exists_predicates => [qw(      age email phone )],
        };
      }

DESCRIPTION
    Class::XSAccessor is able to provide you with a constructor for your
    class, but it's fairly limited. It basically just does:

      sub new {
        my $class = shift;
        bless { @_ }, ref($class)||$class;
      }

    Class::XSConstructor goes a little further and supports all Moose's
    constructor features plus a few more. (That doesn't mean it supports Moose
    features unrelated to constructors!)

    *   Supports initialization from a hashref as well as a list of key-value
        pairs.

    *   Only initializes the attributes you specified. Given the example in
        the synposis:

          my $obj = Person->new(name => "Alice", height => "170 cm");

        The height will be ignored because it's not a defined attribute for
        the class. (In strict mode, an error would be thrown because of the
        unrecognized parameter instead of it simply being ignored.)

    *   Supports required attributes using an exclamation mark. The name
        attribute in the synopsis is required.

        When multiple required attributes are missing, the constructor will
        only report the first one it encountered, based on the order the
        attributes were declared in. This is for compatibility with Moo and
        Moose error messages, which also only report the first missing
        required attribute.

    *   Supports defaults and builders.

        For example:

          use Class::XSConstructor name => { default => '__ANON__' };

        Or:

          use Class::XSConstructor name => { default => sub { return '__ANON__' } };

        Or:

          use Class::XSConstructor name => { builder => '__fallback_name' };
          sub __fallback_name {
            return '__ANON__';
          }

        You can alternatively provide a string of Perl code that will be
        evaluated to generate the default:

          use Class::XSConstructor name => { default => \'sprintf("__%s__", uc "anon")' };

        If you expect subclasses to need to override defaults, use a builder.
        Subclasses can simply provide a method of the same name.

        The XS code has special faster code paths for the following defaults
        which are all very common values to choose as defaults:

          default => undef,
          default => 0,
          default => 1,
          default => !!0,
          default => !!1,
          default => "",
          default => \'[]',
          default => \'{}',

        If an attribute has a default or builder, its "required" status is
        ignored.

        Builders and coderef defaults are likely to significantly slow down
        your constructor.

    *   Provides support for type constraints.

          use Types::Standard qw(Str Int);
          use Class::XSConstructor (
            "name!"    => Str,
            "age"      => { isa => Int, default => 0 },
            "email"    => Str,
            "phone"    => Str,
          );

        Type constraints can also be provided as coderefs returning a boolean:

          use Types::Standard qw(Str Int);
          use Class::XSConstructor (
            "name!"    => Str,
            "age"      => { isa => Int, default => 0 },
            "email"    => sub { !ref($_[0]) and $_[0] =~ /\@/ },
            "phone"    => Str,
          );

        Type constraints are likely to siginificantly slow down your
        constructor, apart from the following type constraints defined in
        Types::Common which are recognized and handled via a pure C codepath:

        *   These basic types:

            Any, Item, Defined, Ref, Bool, Int, PositiveOrZeroInt, Num,
            PositiveOrZeroNum, Str, NonEmptyStr, ClassName, Object, ScalarRef,
            and CodeRef.

        *   ArrayRef and ArrayRef[x] where x is any of the basic types listed
            above.

        *   HashRef and HashRef[x] where x is any of the basic types listed
            above.

        So for example, a type check for ArrayRef[PositiveOrZeroInt] should be
        very fast.

        When multiple attributes fail their type check, the constructor will
        only report the first one it encountered, based on the order the
        attributes were declared in. This is for compatibility with Moo and
        Moose error messages, which also only report the first failed check.

        Note that Class::XSConstructor is only building your constructor for
        you. For read-write attributes, *checking the type constraint in the
        accessor is your responsibility*.

    *   Type coercions.

        If your type constraint is a Type::Tiny object which provides a
        coercion:

          coerce => 1

        Otherwise:

          foo => {
            default => sub { ... },
            isa     => sub { ... },
            coerce  => sub { my $oldval = $_[0]}; ...; return $newval },
          }

        Type coercions are likely to siginificantly slow down your
        constructor.

    *   Supports `init_arg` like Moose and Moo.

          use Class::XSConstructor 'name' => { init_arg => 'moniker' };
  
          my $obj = __PACKAGE__->new( moniker => 'Bob' );
          say $obj->{name};  # ==> "Bob"

    *   Supports `alias`.

          use Class::XSConstructor 'name' => { alias => [ 'moniker' ] };
  
          my $obj = __PACKAGE__->new( name => 'Bob' );
          say $obj->{name};  # ==> "Bob"
  
          my $obj2 = __PACKAGE__->new( moniker => 'Bob' );
          say $obj2->{name};  # ==> "Bob"

    *   Supports `trigger`, which may be a method name or a coderef. Triggers
        are only fired when the attribute is passed to the constructor
        explicitly. Defaults and builders do not trigger the trigger.

    *   Supports `weak_ref` like Moose and Moo.

          use Class::XSConstructor 'thing' => { weak_ref => !!1 };
  
          my $array  = [];
          my $object = __PACKAGE__->new( thing => $array );
  
          defined $object->{thing} or die;  # lives
  
          undef $array;
  
          defined $object->{thing} or die;  # dies

    *   Custom slot initializers.

          use Class::XSConstructor foo => {
            slot_initializer => sub {
              my ( $object, $value ) = @_;
              $object->{FOO} = $value; 
            },
          };

        One of the jobs that the constructor obviously does is insert each
        value into the relevant slots in the object's underlying hash. In very
        rare cases, you might want to provide a callback to do this. A use
        case might be if you have particular attributes that you wish to store
        using inside-out object techniques, or encrypt before storing.

        Obviously your accessors will also need to be written to be able to
        access the value from wherever you've stored it.

        Custom slot initializers are likely to siginificantly slow down your
        constructor.

    *   Automatic deep data cloning.

        Setting `clone_on_write => 1` will automatically deep clone incoming
        arguments before setting them.

          package Local::Foo {
            use Class::XSConstructor foo => { clone_on_write => 1 };
          }
  
          my @array = ( 1, 2, 3 );
          my $obj = Local::Foo->new( foo => \@array );
  
          push @array, 4; # does not affect the array within $obj.

        It is possible to provide a custom callback to clone a value, which
        may be useful to control clone depth, etc. This is obviously slower
        than the built-in clone functionality.

          package Local::Foo {
            use Class::XSConstructor foo => { clone_on_write => sub {
              my ( $self, $attr_name, $value ) = @_;
              ...;
              return $cloned_value;
            } };
          }

        The result of the callback will be re-checked against the type
        constraint, but will not be coerced.

        Defaults are not cloned. Only values passed from outside are.

    *   Undef-tolerant attributes.

          package My::Class {
            use Class::XSConstructor foo => { undef_tolerant => 1 };
          }
  
          my $thing1 = My::Class->new( foo => 42 );
          exists $thing1->{foo};   # true
  
          my $thing2 = My::Class->new( foo => undef );
          exists $thing2->{foo};   # false

        If an attribute is undef-tolerant, it means that setting it to `undef`
        in the constructor is equivalent to not setting it at all. If it has a
        default, it will be used. Otherwise, if it was a required attribute,
        this will throw an error.

    *   Supports Moose/Moo/Class::Tiny-style `BUILD`, `BUILDALL`, `BUILDARGS`,
        and `FOREIGNBUILDARGS` methods.

        Including `__no_BUILD__`.

    *   Optionally supports strict-style constructors a la
        MooX::StrictConstructor and MooseX::StrictConstructor. To opt in, pass
        "!!" as part of the import line. Although it doesn't really matter
        where in the list you include it, I recommend putting it at the end
        for readability.

          use Class::XSConstructor qw( name! age email phone !! );

        Or:

          use Class::XSConstructor (
            "name!"    => Str,
            "age"      => Int,
            "email"    => sub { !ref($_[0]) and $_[0] =~ /\@/ },
            "phone"    => Str,
            "!!",
          );

        Error messages when violating the strict constructor will list all the
        unexpected arguments, but the order in which they are listed will be
        unpredictable.

        The strict constructor check happens *after* `BUILD` methods have been
        called. Because `BUILD` methods are passed a reference to the init
        args hashref, they can alter it, removing certain keys if they need
        to. For example:

            use v5.36;
    
            package Person {
        
                use Class::XSConstructor qw( fullname !! );
                use Class::XSAccessor { accessors => [ 'fullname' ] };
        
                sub BUILD ( $self, $args ) {
                    if ( exists $args->{given_name} and exists $args->{surname} ) {
                        $self->fullname(
                            join q{ } => (
                                delete $args->{given_name},
                                delete $args->{surname},
                            )
                        );
                    }
                }
            }
    
            my $bob = Person->new( given_name => 'Bob', surname => 'Dobalina' );
            say $bob->fullname;

    *   Constructor names other than `__PACKAGE__->new`:

          use Class::XSConstructor [ 'Person', 'create' ] => qw( name! age email phone );
  
          my $bob = Person->create( name => 'Bob Dobalina' );

        It is NOT possible to create two different constructors for the same
        class with different attributes for each:

          use Class::XSConstructor [ 'Person', 'new_by_phone' ] => qw( name! phone );
          use Class::XSConstructor [ 'Person', 'new_by_email' ] => qw( name! email );

API
    This section documents the API of Class::XSConstructor for other modules
    that wish to wrap its functionality (to perhaps provide additional
    features like accessors). If you are just using Class::XSConstructor to
    install a constructor into your class, you can skip this section of the
    documentation.

  Functions and Methods
    None of the following functions are exported.

    `Class::XSConstructor->import(@optlist)`
        Does all the setup for a class to install the constructor. Will
        determine which class to install the constructor into based on
        `caller` and call the method `new`. You can override this by passing
        an arrayref of the package name to do the setup for, followed by the
        method name for the constructor:

          Class::XSConstructor->import( [ $packagename, $methodname ], @optlist );

        For historical reasons, it is also possible to override the package
        name using:

          local $Class::XSConstructor::SETUP_FOR = 'Some::Package';
          Class::XSConstructor->import( @optlist );

        ... Though this does not allow you to provide a method name.

        Returns nothing.

    Class::XSConstructor::get_metadata( $package )
        Get a copy of the metadata that Class::XSConstructor holds for the
        package. It is probably not wise to tamper with it too much, as it is
        a recipe for segfaults.

  Clearing Cached Data
    The constructor and destructor methods created by Class::XSConstructor and
    Class::XSDestructor cache a lot of data the first time they get called.

    If you do any of the following after an object has already been
    constructed, you will need to clear those caches.

    *   Changing @ISA, including the @ISA for any ancestor packages.

    *   Changing the metadata returned by `get_metadata`.

    *   Defining a new `BUILD` or `DEMOLISH` method, or redefining an existing
        one, in either your class or any ancestor or descendent class.

    To clear all cached data:

      # Clear the data cached in C structs by the constructor,
      # including details of any attributes, plus the list of
      # BUILD methods for Your::Class itself.
      Your::Class->XSCON_CLEAR_CONSTRUCTOR_CACHE;
  
      # Clear the data cached in Perl data structures by the
      # constructor. This is mostly used when `new` is called
      # on a non-Class::XSConstructor class that inherits from
      # a Class::XSConstructor class without overriding `new`.
      %Class::XSAccessor::BUILD_CACHE = ();
  
      # Clear the data cached in C structs by the destructor. This
      # is just the list of DEMOLISH methods for your class itself.
      Your::Class->XSCON_CLEAR_DESTRUCTOR_CACHE
        if Your::Class->can('XSCON_CLEAR_DESTRUCTOR_CACHE');
  
      # Clear the data cached in Perl data structures by the
      # destructor. This is mostly used when `DESTROY` is called
      # on a non-Class::XSConstructor class that inherits from
      # a Class::XSConstructor class without overriding `DESTROY`.
      %Class::XSAccessor::DEMOLISH_CACHE = ();

CAVEATS
    Inheritance will automatically work if you are inheriting from another
    Class::XSConstructor class, but you need to set @ISA *before* importing
    from Class::XSConstructor (which will happen at compile time!)

    An easy way to do this is to use parent before using Class::XSConstructor.

      package Employee {
        use parent "Person";
        use Class::XSConstructor qw( employee_id! );
        use Class::XSAccessor { getters => [qw(employee_id)] };
      }

    Using any of the following features means that your fast XS constructor
    will be calling your own coderefs, which are presumably written in Perl
    and thus not so fast. This can slow down your constructor significantly:

    *   Builders and defaults, except for the eight specially optimized
        default values.

    *   Triggers.

    *   Type constraints (except for the specially optimized ones) and type
        coercions.

    *   Custom slot initializers.

    *   Defining any `BUILD` or `BUILDARGS` methods or inheriting from classes
        which do.

    These can all be useful features of course, but if speed is critical,
    consider looking at ways to eliminate them.

INSTALLATION
    If the environment variable `PERL_XS_STRICTC89` is set to true when
    running Makefile.PL, strict C89 flags will be passed to the C compiled
    when compiling Class::XSConstructor. This will also happen if Makefile.PL
    detects it is likely being run in the author's development environment.

    In general, the module should work the same in either case.

SEE ALSO
    Class::Tiny, Class::XSAccessor, Class::XSReader, Class::XSDestructor,
    Class::XSDelegation.

    A user-friendly wrapper for all the Class::XS* modules: Marlin.

AUTHOR
    Toby Inkster <tobyink@cpan.org>.

    Incorporates parts of Clone, originally by Ray Finch <rdf@cpan.org> and
    maintained by Breno G. de Oliveira <garu@cpan.org>, Nicolas Rochelemagne
    <atoomic@cpan.org>, and Florian Ragwitz <rafl@debian.org>.

THANKS
    To everybody in *#xs* on irc.perl.org.

COPYRIGHT AND LICENCE
    This software is copyright (c) 2018-2019, 2025-2026 by Toby Inkster.

    This is free software; you can redistribute it and/or modify it under the
    same terms as the Perl 5 programming language system itself.

DISCLAIMER OF WARRANTIES
    THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
    WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
    MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.

