#ifndef cathlibcpp_hoistctdt_H
#define cathlibcpp_hoistctdt_H

// File:       hoistctdt.h
// Author:     (c) Miles Sabin, 1997
// Purpose:    hoisted constructors/destructors.


#ifndef included_stddef_H
#define included_stddef_H
#include <stddef.h>                    // for size_t
#endif

#ifndef cathlibcpp_bool_H
#include "bool.h"
#endif

#ifndef cathlibcpp_config_H
#include "config.h"
#endif

#ifndef cathlibcpp_hoistctdtp_H
#include "hoistctdtp.h"
#endif

#ifndef cathlibcpp_stringfwd_H
#include "stringfwd.h"
#endif


template<class T>
class HoistConstructorDestructor : public HoistConstructorDestructorProtocol
{
  public:

    // constructors
    static HoistConstructorDestructor<T>& instance();
    ~HoistConstructorDestructor();

    // accessors
    void construct(void* at, void const* value) const;
    void destroy(void* at) const;

    void assign(void* lhs, void const* rhs) const;

    size_t size() const;

  private:

    HoistConstructorDestructor() {}

    static HoistConstructorDestructor<T>* singleton_;
};


template<class T>
inline HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(T*)
{
  return HoistConstructorDestructor<T>::instance();
}

// specializations for builtin types

HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(char*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(short*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(int*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(long*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned char*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned short*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned int*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned long*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(float*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(double*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(string*);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(char**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(char const**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(short**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(int**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(long**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned char**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned char const**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned short**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned int**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(unsigned long**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(float**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(double**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(string**);
HoistConstructorDestructorProtocol& get_hoist_constructor_destructor(void**);

#endif
