Exemple #1
0
			int_type underflow()
			{
				if ( gptr() < egptr() )
					return static_cast<int_type>(*uptr());
					
				assert ( gptr() == egptr() );
					
				char * midptr = buffer.begin() + pushbackspace;
				uint64_t const copyavail = 
					std::min(
						// previously read
						static_cast<uint64_t>(gptr()-eback()),
						// space we have to copy into
						static_cast<uint64_t>(midptr-buffer.begin())
					);
				::std::memmove(midptr-copyavail,gptr()-copyavail,copyavail);

				stream.read(midptr, buffer.end()-midptr);
				size_t const n = stream.gcount();
				streamreadpos += n;

				setg(midptr-copyavail, midptr, midptr+n);

				if (!n)
					return traits_type::eof();
				
				return static_cast<int_type>(*uptr());
			}
Exemple #2
0
			int_type underflow()
			{
				if ( gptr() < egptr() )
					return static_cast<int_type>(*uptr());
					
				assert ( gptr() == egptr() );
				
				char * midptr = buffer.begin() + pushbackspace;
				uint64_t const copyavail = 
					std::min(
						// previously read
						static_cast<uint64_t>(gptr()-eback()),
						// space we have to copy into
						static_cast<uint64_t>(midptr-buffer.begin())
					);
				::std::memmove(midptr-copyavail,gptr()-copyavail,copyavail);
				
				size_t n = 0;
				bool done = false;
				
				while ( ! done )
				{
					BgzfInflateInfo const info = stream.readAndInfo(midptr, buffer.end()-midptr);						
					n = info.uncompressed;
					
					// non eof block
					if ( n )
					{
						streamreadpos += n;
						done = true;			
					}
					else
					{
						// eof block at end of stream
						if ( info.streameof )
						{
							done = true;
						}
						// intermediate empty block, skip it
						else
						{
						
						}
					}
				}

				setg(midptr-copyavail, midptr, midptr+n);

				if (!n)
					return traits_type::eof();
									
				return static_cast<int_type>(*uptr());
			}
std::unique_ptr<C4NetpuncherPacket> C4NetpuncherPacket::Construct(const C4NetIOPacket& rpack) {
	if (!rpack.getPData() || *rpack.getPData() != C4NetpuncherProtocolVersion) return nullptr;
	try {
		switch (rpack.getStatus())
		{
			case PID_Puncher_AssID: return uptr(new C4NetpuncherPacketAssID(rpack));
			case PID_Puncher_SReq:  return uptr(new C4NetpuncherPacketSReq(rpack));
			case PID_Puncher_CReq:  return uptr(new C4NetpuncherPacketCReq(rpack));
			case PID_Puncher_IDReq: return uptr(new C4NetpuncherPacketIDReq(rpack));
			default: return nullptr;
		}
	}
	catch (StdCompiler::Exception *e) { delete e; return nullptr; }
	catch (...) { return nullptr; }
}
Exemple #4
0
cudaError_t NVEncFilter::AllocFrameBuf(const FrameInfo& frame, int frames) {
    if (m_pFrameBuf.size() == frames
        && !cmpFrameInfoCspResolution(&m_pFrameBuf[0]->frame, &frame)) {
        //すべて確保されているか確認
        bool allocated = true;
        for (int i = 0; i < m_pFrameBuf.size(); i++) {
            if (m_pFrameBuf[i]->frame.ptr == nullptr) {
                allocated = false;
                break;
            }
        }
        if (allocated) {
            return cudaSuccess;
        }
    }
    m_pFrameBuf.clear();

    for (int i = 0; i < frames; i++) {
        unique_ptr<CUFrameBuf> uptr(new CUFrameBuf(frame));
        uptr->frame.ptr = nullptr;
        auto ret = uptr->alloc();
        if (ret != cudaSuccess) {
            m_pFrameBuf.clear();
            return ret;
        }
        m_pFrameBuf.push_back(std::move(uptr));
    }
    m_nFrameIdx = 0;
    return cudaSuccess;
}
Exemple #5
0
bool sCopyFile(const char *source,const char *dest,bool failifexists)
{
  sFile *sf = sOpenFile(source,sFA_Read);
  sFile *df = sOpenFile(dest,sFA_Write);
  bool ok = 0;
  if(sf && df)
  {
    uptr size = uptr(sf->GetSize());
    uptr block = 1024*1024;
    uint8 *buffer = new uint8[block];
    
    while(size>0)
    {
      uptr chunk = sMin(block,size);
      sf->Read(buffer,chunk);
      df->Write(buffer,chunk);
      size -= chunk;
    }
  }
  if(sf) if(!sf->Close()) ok = 0;
  if(df) if(!df->Close()) ok = 0;
  
  if(!ok)
    sLogF("file","failed to copy file <%s> to <%s>",source,dest);
  else
    sLogF("file","copy file <%s> to <%s>",source,dest);
  return ok;
}
Exemple #6
0
			int_type underflow()
			{
				// if there is still data, then return it
				if ( gptr() < egptr() )
					return static_cast<int_type>(*uptr());

				assert ( gptr() == egptr() );

				uint64_t const symsleft = ((n+(addterm?1:0))-symsread);
				
				if ( symsleft == 0 )
					return traits_type::eof();

				uint64_t const lasttermblock = addterm ? ((symsleft <= buffersize)?1:0) : 0;
				uint64_t const symstoread = std::min(symsleft-lasttermblock,buffersize);
				
				uint64_t const wordstoread = (symstoread * b + (bitsperentity-1))/bitsperentity;
				uint64_t const bytestoread = wordstoread * (bitsperentity/8);
				
				// load packed data into memory
				stream.read ( reinterpret_cast<char *>(C.begin()) , bytestoread );
				if ( stream.gcount() != static_cast<int64_t>(bytestoread) )
				{
					::libmaus2::exception::LibMausException se;
					se.getStream() << "PacDecoderBuffer::underflow() failed to read " << bytestoread << " bytes." << std::endl;
					se.finish();
					throw se;
				}
			
				// decode array
				::libmaus2::bitio::ArrayDecode::decodeArray(
					C.begin(), reinterpret_cast<uint8_t *>(buffer.begin()), symstoread, 2
				);
				
				if ( addterm )
					for ( uint64_t i = 0; i < symstoread; ++i )
						buffer[i] += 1;
				if ( lasttermblock )
					buffer[symstoread] = 0;
				
				setg(buffer.begin(),buffer.begin(),buffer.begin()+symstoread+lasttermblock);

				symsread += symstoread+lasttermblock;
				
				return static_cast<int_type>(*uptr());
			}
    /**
     * buffer underflow callback
     * @return next symbol
     **/
    typename base_type::int_type underflow()
    {
        if ( base_type::gptr() < base_type::egptr() )
            return static_cast<typename base_type::int_type>(*uptr());

        assert ( base_type::gptr() == base_type::egptr() );

        char_type * midptr = buffer.begin() + pushbackspace;
        uint64_t const copyavail =
            std::min(
                // previously read
                static_cast<uint64_t>(base_type::gptr()-base_type::eback()),
                // space we have to copy into
                static_cast<uint64_t>(midptr-buffer.begin())
            );
        ::std::memmove(midptr-copyavail,base_type::gptr()-copyavail,copyavail*sizeof(char_type));

        if ( static_cast<int64_t>(stream.tellg()) == static_cast<int64_t>(0) )
        {
            stream.seekg(infilesize);
            stream.clear();
        }

        uint64_t const rspace = stream.tellg();
        uint64_t const toread = std::min(rspace,static_cast<uint64_t>(buffer.end()-midptr));

        stream.seekg(-static_cast<int64_t>(toread),std::ios::cur);
        stream.clear();

        stream.read(midptr, toread);
        size_t const n = stream.gcount();
        assert ( n == toread );
        std::reverse(midptr,midptr+n);
        streamreadpos += n;

        stream.seekg(-static_cast<int64_t>(toread),std::ios::cur);
        stream.clear();

        base_type::setg(midptr-copyavail, midptr, midptr+n);

        if (!n)
            return base_type::traits_type::eof();

        return static_cast<typename base_type::int_type>(*uptr());
    }
Exemple #8
0
			unique_ptr_type uclone() const
			{
				unique_ptr_type uptr(new this_type);
				
				uptr->postr = libmaus2::util::shared_ptr<std::ostringstream>::type(new std::ostringstream(postr->str()));
				uptr->s = s;
				
				return UNIQUE_PTR_MOVE(uptr);
			}
Exemple #9
0
void main()
{
    std::unique_ptr<int> uptr(new int(10));
    std::promise<std::string> pr;
    std::cout << (void *)(uptr.get()) << std::endl;
    std::future<std::string> fut = pr.get_future();
    std::thread th(fun, std::move(pr), std::move(uptr));
    std::cout << "Main receiving.\n";
    std::string s = fut.get();
    std::cout << s << std::endl;
    th.join();
}
			int_type underflow()
			{
				// if there is still data, then return it
				if ( gptr() < egptr() )
					return static_cast<int_type>(*uptr());
					
				assert ( gptr() == egptr() );

				// load data
				size_t const g = doRead(buffer.begin(),buffersize);
				
				// set buffer pointers
				setg(buffer.begin(),buffer.begin(),buffer.begin()+g);

				// update start of buffer position
				readpos += g;

				if ( g )
					return static_cast<int_type>(*uptr());
				else
					return traits_type::eof();
			}
			int_type underflow()
			{
				// if there is still data, then return it
				if ( gptr() < egptr() )
					return static_cast<int_type>(*uptr());

				assert ( gptr() == egptr() );

				// number of bytes for putback buffer
				uint64_t const putbackcopy = std::min(
					static_cast<uint64_t>(gptr() - eback()),
					putbackspace
				);
				// copy bytes
				std::copy(
					gptr()-putbackcopy,
					gptr(),
					buffer.begin() + putbackspace - putbackcopy
				);
				
				// load data
				uint64_t const uncompressedsize = stream.read(
						buffer.begin()+putbackspace,
						buffer.size()-putbackspace
					);
				
				// set buffer pointers
				setg(
					buffer.begin()+putbackspace-putbackcopy,
					buffer.begin()+putbackspace,
					buffer.begin()+putbackspace+uncompressedsize);

				symsread += uncompressedsize;
				
				if ( uncompressedsize )
					return static_cast<int_type>(*uptr());
				else
					return traits_type::eof();
			}
Exemple #12
0
void FixedSwap(T& a, T& b) {
  constexpr size_t kMaxStackUsage = 4 * 1024;

  if (sizeof(a) < kMaxStackUsage) {
    T tmp(a);
    a = b;
    b = tmp;
  } else {
    std::unique_ptr<T> uptr(new T(a));
    a = b;
    b = *uptr;
  }
}
Exemple #13
0
NVENCSTATUS NVEncFilter::filter_as_interlaced_pair(const FrameInfo *pInputFrame, FrameInfo *pOutputFrame, cudaStream_t stream) {
    if (!m_pFieldPairIn) {
        unique_ptr<CUFrameBuf> uptr(new CUFrameBuf(*pInputFrame));
        uptr->frame.ptr = nullptr;
        uptr->frame.pitch = 0;
        uptr->frame.height >>= 1;
        uptr->frame.picstruct = RGY_PICSTRUCT_FRAME;
        uptr->frame.flags &= ~(RGY_FRAME_FLAG_RFF | RGY_FRAME_FLAG_RFF_COPY | RGY_FRAME_FLAG_RFF_TFF | RGY_FRAME_FLAG_RFF_BFF);
        auto ret = uptr->alloc();
        if (ret != cudaSuccess) {
            m_pFrameBuf.clear();
            return NV_ENC_ERR_OUT_OF_MEMORY;
        }
        m_pFieldPairIn = std::move(uptr);
    }
static int ioctl_create(struct db_ioctl_create __user *u)
{
        struct db_ioctl_create k;
        char *key;
        const struct db_template *template;
        int status;
        void *p;

        if (copy_from_user(&k, u, sizeof(k)) != 0)
                return -EFAULT;
        key = memdup_from_user(uptr(u, k.key), k.key_len + 1);
        if (IS_ERR(key))
                return (int)PTR_ERR(key);

        LOG_ENTRY("%s", key);

        status = db_template_get(key, &template);
Exemple #15
0
std::string SSLSessionImpl::serialize(void) const {
  std::string ret;

  // Get the length first, then we know how much space to allocate.
  auto len = i2d_SSL_SESSION(session_, nullptr);

  if (len > 0) {
    std::unique_ptr<unsigned char[]> uptr(new unsigned char[len]);
    auto p = uptr.get();
    auto written = i2d_SSL_SESSION(session_, &p);
    if (written <= 0) {
      VLOG(2) << "Could not serialize SSL_SESSION!";
    } else {
      ret.assign(uptr.get(), uptr.get() + written);
    }
  }
  return ret;
}
int main() {
	int a = 10;
	std::shared_ptr<int> ptra = std::make_shared<int>(a);
	std::shared_ptr<int> ptra2(ptra); //copy
	std::cout << ptra.use_count() << std::endl;

	int b = 20;
	int *pb = &a;

	//std::shared_ptr<int> ptrb = pb;  //error
	std::shared_ptr<int> ptrb = std::make_shared<int>(b);
	ptra2 = ptrb; //assign
	pb = ptrb.get(); //获取原始指针

	std::cout << ptra.use_count() << std::endl;
	std::cout << ptrb.use_count() << std::endl;

	int c = 5;

	std::unique_ptr<int> uptr(&c);
	*uptr = 6;
	std::cout << "[Debug] " << c << std::endl;

	std::unique_ptr<int> uptr2 = std::move(uptr);
	uptr2.release();

	std::shared_ptr<int> sh_ptr = std::make_shared<int>(10);
	std::cout << sh_ptr.use_count() << std::endl;

	std::weak_ptr<int> wp(sh_ptr);
	std::cout << wp.use_count() << std::endl;

	if (!wp.expired()) {
		std::shared_ptr<int> sh_ptr2 = wp.lock();
		*sh_ptr = 100;
		std::cout << wp.use_count() << std::endl;
	}

	return 0;
}
Exemple #17
0
void TestProtection()
	{
	test.Next(_L("Test protection"));
	TBool jit=User::JustInTime();
	User::SetJustInTime(EFalse);
	TUint x=0xffffffff;
	TBuf8<64> ubuf;
	TPtrC8 uptrc(ubuf.Ptr(),11);
	TPtr8 uptr((TUint8*)ubuf.Ptr(),1,20);
	TPtrC8 kptrc(Kern,1);
	TPtr8 kptr(Kern,10,256);
	TPtrC8 gptrc(Garbage,1);
	TPtr8 gptr(Garbage,10,256);
	RunTestInThread(GlobalReadThread,&x,&KLitKernExec,EKUDesInfoInvalidType);
	RunTestInThread(GlobalReadThread,&ubuf,NULL,KErrNone);
	RunTestInThread(GlobalReadThread,&uptr,NULL,KErrNone);
	RunTestInThread(GlobalReadThread,&uptrc,&KLitKernExec,EKUDesInfoInvalidType);
	RunTestInThread(GlobalReadThread,&kptrc,&KLitKernExec,EKUDesInfoInvalidType);
	RunTestInThread(GlobalReadThread,&gptrc,&KLitKernExec,EKUDesInfoInvalidType);
	RunTestInThread(GlobalReadThread,&gptr,&KLitKernExec,ECausedException);
	if (KernProt)
		{
		RunTestInThread(GlobalReadThread,Kern,&KLitKernExec,ECausedException);
		RunTestInThread(GlobalReadThread,&kptr,&KLitKernExec,ECausedException);
		}
	RunTestInThread(GlobalWriteThread,&x,&KLitKernExec,EKUDesInfoInvalidType);
	RunTestInThread(GlobalWriteThread,&ubuf,NULL,KErrNone);
	RunTestInThread(GlobalWriteThread,&uptr,NULL,KErrNone);
	RunTestInThread(GlobalWriteThread,&uptrc,NULL,KErrNone);
	RunTestInThread(GlobalWriteThread,&gptrc,&KLitKernExec,ECausedException);
	RunTestInThread(GlobalWriteThread,&gptr,&KLitKernExec,ECausedException);
	if (KernProt)
		{
		RunTestInThread(GlobalWriteThread,Kern,&KLitKernExec,ECausedException);
		RunTestInThread(GlobalWriteThread,&kptrc,&KLitKernExec,ECausedException);
		RunTestInThread(GlobalWriteThread,&kptr,&KLitKernExec,ECausedException);
		}
	User::SetJustInTime(jit);
	}
void func()
{
  boost::interprocess::unique_ptr<int, boost::default_delete<int> > uptr(new int(5));
  p.set_value_at_thread_exit(boost::move(uptr));
}
void func()
{
  boost::csbl::unique_ptr<int> uptr(new int(5));
  p.set_value_at_thread_exit(boost::move(uptr));
}
Exemple #20
0
	void DNServer::mainLoop()
	{
        #ifdef __linux
            typedef int SOCKET;
            typedef sockaddr SOCKADDR;
            typedef sockaddr_in SOCKADDR_IN;
            const int INVALID_SOCKET = -1;
            #define closesocket(X) close(X)
        #endif
		SOCKET servSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		if (servSock == INVALID_SOCKET)
			throw logic_error("DNServer: socket error");

		SOCKET cliSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
		if (cliSock == INVALID_SOCKET)
		{
			closesocket(servSock);
			throw logic_error("DNServer: socket error");
		}

		try
		{
			SOCKADDR_IN ssin = { 0 };
			ssin.sin_family = AF_INET;
			ssin.sin_addr.s_addr = inet_addr(cfpars["main"]["bindaddr"].c_str());
			ssin.sin_port = htons(stoi(cfpars["main"]["bindport"]));

			SOCKADDR_IN assin = { 0 };
			assin.sin_family = AF_INET;
			assin.sin_addr.s_addr = inet_addr(cfpars["main"]["rootdns"].c_str());
			assin.sin_port = htons(stoi(cfpars["main"]["rootdnsport"]));

			if (::bind(servSock, reinterpret_cast<SOCKADDR*>(&ssin), sizeof(ssin)))
					throw logic_error("DNServer: bind error");

			unsigned char packet[BUFSIZE];
			while (1)
			{
				memset(packet, 0, sizeof(packet));
				size_t recSize;
				SOCKADDR_IN ssinf = { 0 };
                #ifdef _WIN32
                    int ssinsz = sizeof(ssinf);
                #elif __linux
                    socklen_t ssinsz = sizeof(ssinf);
                #endif
				if ((recSize = recvfrom(servSock, reinterpret_cast<char*>(packet), sizeof(packet), 0, reinterpret_cast<SOCKADDR*>(&ssinf), &ssinsz)) > 0)
				{
					DnsResponse response(packet);
					if (filter(inet_ntoa(ssinf.sin_addr)) && processClient(response))
					{
						// обработать запрос и отдать ответ
						size_t respsize = response.size();

						response.setTruncated(respsize >= 512);

						if (respsize > sizeof(packet))
						{
							unique_ptr<unsigned char[]> uptr(new unsigned char[respsize]);
							response.dump(uptr.get());
							sendto(servSock, reinterpret_cast<char*>(uptr.get()), respsize, 0, reinterpret_cast<SOCKADDR*>(&ssinf), sizeof(ssinf));
						}
						else
						{
							memset(packet, 0, sizeof(packet));
							response.dump(packet);
							sendto(servSock, reinterpret_cast<char*>(packet), respsize, 0, reinterpret_cast<SOCKADDR*>(&ssinf), sizeof(ssinf));
						}
					}
					else
					{
						// данный тип запроса не поддерживаетс¤
						// отправить запрос основному серверу
						sendto(cliSock, reinterpret_cast<char*>(packet), recSize, 0, reinterpret_cast<SOCKADDR*>(&assin), sizeof(assin));
						memset(packet, 0, sizeof(packet));
						int rfms = recvfrom(cliSock, reinterpret_cast<char*>(packet), sizeof(packet), 0, NULL, NULL);
						sendto(servSock, reinterpret_cast<char*>(packet), rfms, 0, reinterpret_cast<SOCKADDR*>(&ssinf), sizeof(ssinf));
					}
				}
			}
		}
		catch (...)
		{
			closesocket(servSock);
			closesocket(cliSock);
			throw;
		}
		
		closesocket(servSock);
		closesocket(cliSock);
	}
static int main_v()
{
	//reasons to avoid regular pointers...
		//* From just the declaration, you don't know if its your responsibility to destroy the pointer.
		//		*->You also cannot tell the proper mechanism for deleting, is there a logging function?
		//* A pointer declartion may refer to a single object or an array of objects; it's ambiguous!
		//		*->this also leads to the an ambiguity for deleting, should you use delete or delete[]?
		//* From a raw pointer, it is hard to make sure it is destroyed only once, and that there are no dangling pointers.
		//* Its hard to tell if you have resource leaks 

	//std::auto_ptr should be avoided! its like a unique pointer but worse!
	{
		std::auto_ptr<M> dep_aptr = std::auto_ptr<M>(new M());
		dep_aptr->doWork();

		//autoptr copy operations are attempts at move semantics; this is cpp98, before move semantics were at thing.
		std::auto_ptr<M> transfer = dep_aptr; //nulls out dep_aptr
		transfer->doWork();

		//the move hijacking of copies led to weird behavior, such as when trying to store auto_ptrs in containers, or copying an autoptr being set to null
		std::vector<std::auto_ptr<M>> container;
		//container.push_back(transfer);//doesn't compile
		//container.push_back(std::auto_ptr<M>(new M())); //this WILL compile, but it isn't what we want, we want to transfer the auto_ptr to the container! 
		//container[0]->doWork(); //cannot store the transfer ptr in the container, so better not call this

		//ALWAYS prefer unique pointer, don't use autoptr... its removed in cpp17
	}

	//unique pointers are small like raw pointers, but have their lifetime managed! 
	//They also have copy operations and move operations! This makes superior to auto_ptr in every way!
	{
		//You can assume that unique pointers are the size of raw pointers, or just barely larger than raw pointers.
		M* raw_ptr = nullptr;
		std::unique_ptr<M> u_ptr1(new M(5));
		auto u_ptr2 = std::make_unique<M>(5);

		//both these pointers are of size 8 bytes!
		std::cout << "size of a raw ptr: " << sizeof(raw_ptr) << std::endl;
		std::cout << "size of a unique ptr: " << sizeof(u_ptr1) << std::endl;

		//You can move unique pointers, but you can't copy them!
		//std::unique_ptr<M> u_ptr3 = u_ptr1;  //C2280: copy ctor is deleted!
		//std::unique_ptr<M> u_ptr3(u_ptr1);	//C2280: copy ctor is deleted
		std::unique_ptr<M> u_ptr3 = std::move(u_ptr1); //compiles fine!			//sets u_ptr1 to nullptr
		std::unique_ptr<M> uptr4(std::move(u_ptr2)); //compiles!				//sets u_ptr2 to nullptr
	}

	{
		//unique pointers make good return types for factory methods because they cant automatically be converted to shared pointers!
		std::unique_ptr<M> ptr1 = factory(true);
		auto ptr2 = factory(false);
		std::shared_ptr<M> ptr3 = factory(true);
	}

	{
		auto ptr1 = advanced_factory(Type::M, 0); //will cause a compile error unless all types can take an integer as parameter!
		auto ptr2 = advanced_factory(Type::N, 1); //will cause a compile error unless all types can take an integer as parameter!
		auto ptr3 = advanced_factory(Type::O, 2); //will cause a compile error unless all types can take an integer as parameter!
		//auto ptr1 = advanced_factory(Type::M);
		//auto ptr2 = advanced_factory(Type::N);
		//auto ptr3 = advanced_factory(Type::O);
	}


	{
		//different deleters may change the size of the unique pointer (this is NOT true for shared pointers, because shared pointers store deleters in their shared control block)
		//prefer deleters that are specified by lambdas, they're even smaller than function pointers. In fact, lambda's don't add any size at all to the function pointer!
		auto deleter_lambda = [](M* rawPtr) {std::cout << "logging delete" << std::endl; delete rawPtr; };
		void(*deleter_fp)(M*) = &deleter_func;
		std::function<void(M*)> deleter_func_obj = &deleter_func;

		//notice that these unique pointers specify their type to include the type of the deleter (look at ctors, auto used for compactness)
		auto uptr_lambda = std::unique_ptr<M, decltype(deleter_lambda)>(new M, deleter_lambda);
		auto uptr_fptr = std::unique_ptr<M, decltype(deleter_fp)>(new M, deleter_fp);
		auto uptr_func_obj = std::unique_ptr<M, decltype(deleter_func_obj)>(new M, deleter_func_obj);

		std::cout << "The size of the uptr with " << "a lambda deleter: " << sizeof(uptr_lambda) << std::endl;				//8 bytes
		std::cout << "The size of the uptr with " << "a function pointer deleter: " << sizeof(uptr_fptr) << std::endl;		//16 bytes
		std::cout << "The size of the uptr with " << "a function obj deleter: " << sizeof(uptr_func_obj) << std::endl;		//72 bytes
	}

	{
		//using unique pointers are even safe with exceptions! stack unwinding will call dtor on uptr
		try
		{
			//stack unwind the scopes
			{
				{
					auto deleter_lambda = [](M* rawPtr) {std::cout << "deleting " << rawPtr << std::endl; delete rawPtr; };
					auto ptr = std::unique_ptr<M, decltype(deleter_lambda)>(new M, deleter_lambda);
					std::cout << "\n\ncreated " << ptr.get() << " " << std::endl;
					std::cout << "throwing exception, will dtor be called in stack unwinding?" << std::endl;
					throw std::runtime_error("exception");
				}
			}
		}
		catch (std::runtime_error e)
		{
			std::cout << "exception handled!" << std::endl;
		}
		//output:
		//created 000002B6C5DD0770
		//throwing exception, will dtor be called in stack unwinding ?
		//deleting 000002B6C5DD0770
		//M dtor
		//exception handled!
	}

	{
		//note the syntax below is illegal because it was deemed problematic
		//std::unique_ptr<M> uptr = new M; //IE no conversions directly from pointer to uptr.

		//there are two forms of unique pointers (this is not true for shared ptr), the single object form and the array form.
		//these different forms have different apis, for example the [] operator is removed from the single object form.
		auto uptr_obj = std::make_unique<M>();
		//uptr_obj[0]; //not present in single object api!

		//std::unique_ptr<M[]> uptr_array(new M[5]);
		std::unique_ptr<M[]> uptr_array_cpp14 = std::make_unique<M[]>(5); //make an array of size 5 in cpp14
		uptr_array_cpp14[5]; //operator is okay!
		//uptr arrays should be avoided in favor of std::vector or other containers; but you may need it when dealing with C apis.

		//note: unique pointers are good for implementing the pImpl idiom
	}
	//you can easily convert to a shared pointer from a unique pointer (but not the other way around)
	//this is why your factory methods should return unique pointers, instead of shared pointers. Doing so allows the caller to decided the ownership of the pointer.
	{
		std::unique_ptr<M> uptr = std::make_unique<M>();
		std::shared_ptr<M> sptr = std::move(uptr); //requires that you move ownership!
	}

	{
		//transferring ownership with custom deleters? works :3
		auto deleter_lambda = [](M* rawPtr) {std::cout << "super custom deleting " << rawPtr << std::endl; delete rawPtr; };
		std::unique_ptr<M, decltype(deleter_lambda)> uptr(new M, deleter_lambda);
		std::shared_ptr<M> sptr = std::move(uptr);
	}

	std::cin.get();
}