C++03 smart pointer with free() - c++

I have a char pointer that I need to transfer ownership of, and I would rather not have to handle its lifecycle myself if possible. The memory is allocated using malloc (no choice here).
As such I'm looking for something like C++11's unique_ptr, which manages ownership and allows a custom Deleter to be provided.
As the title suggests, I don't have access to C++11 features though. auto_ptr isn't a goer as far as I'm aware, as it calls delete rather than free.
Is there an appropriate smart pointer in this case, or will I have to manage the freeing of the memory myself?

As an alternative to writing it yourself you can introduce a dependency on Boost and just use boost::shared_ptr.
But for comparison, here’s minimal off-the-cuff C++11 and later code for an malloc/free based ownership transfer pointer, like std::unique:
template< class Type >
class My_ptr
{
private:
Type* p_;
My_ptr( My_ptr const& ) = delete;
operator=( My_ptr const& ) -> My_ptr& = delete;
public:
auto operator->() const
-> Type*
{ return p; }
auto operator*() const
-> Type&
{ return *p; }
~My_ptr() { free( p_ ); }
My_ptr( Type* p )
: p_( p )
{}
My_ptr( My_ptr&& other )
: p_( other.p_ )
{ other.p_ = nullptr; }
};
As you can see it's not much code in C++11.
Disclaimer: the above code has not been seen by compiler.
In C++03 the main problem is how to make it possible to return the smart pointer from a function, without allowing general copy construction, which would wreak havoc.
The solution used by std::auto_ptr was to involve a mediator pointer carrier class with implicit conversions. This was complex. I remember encountering a great number of idiosyncrasies in Visual C++'s implementation of std::auto_ptr, when I wrote a (once referenced by Wikipedia) pointer tutorial.
The code below, hopefully valid C++03 (tested with g++ -std=c++03), is instead based on the programmer explicitly indicating where a move operation is desired, by calling the as_movable member function. It uses volatile as a kind of tag, to ensure that only the moving constructor can fit when the result of as_movable is used as a constructor argument. The idea of using volatile as a tag in C++03, though in a quite different context, was once introdued by Andrei Alexandrescu; possibly by others before him, but as far as I recall his usage was where I first encountered that idea.
The placement allocation and deallocation operators, operator new and operator delete, are defined for exception safety. In particular, the placement operator delete defined here is only called implicitly, by a new-expression, when the relevant type's constructor indicates failure by throwing an exception. Then the memory is deallocated, using this operator, before the exception is re-thrown.
#include <exception> // std::terminate
#include <new> // std::bad_alloc
#include <stddef.h> // size_t
#include <stdlib.h> // malloc, free, NULL
#define MY_NEW( type, args ) \
::new type args
#define MY_MALLOC( type, args ) \
::new( my::c_memory_management ) type args
namespace my {
struct C_memory_management {};
C_memory_management const c_memory_management = C_memory_management();
} // namespace my
void*
operator new( size_t const size, my::C_memory_management )
{
void* result = malloc( size );
if( not result ) { throw std::bad_alloc(); }
return result;
}
// This operator is (only) called automatically by a new-expression where the
// constructor for the type, throws. After the call the exception is re-thrown.
void operator delete( void* const p, my::C_memory_management )
{
free( p );
}
#ifdef SUPPORT_ARRAYS
void*
operator new[]( size_t const size, my::C_memory_management const cmm )
{
return operator new( size, cmm );
}
void operator delete[]( void* const p, my::C_memory_management const cmm )
{
operator delete( p, cmm );
}
#endif
namespace my {
template< class Referent >
struct Destruction_via_delete_
{
static void destroy( Referent const* p )
{
try
{
delete p;
}
catch( ... )
{
std::terminate();
}
}
};
template< class Referent >
struct Destruction_via_free_
{
static void destroy( Referent const* p )
{
try
{
p->~Referent();
}
catch( ... )
{
std::terminate();
}
::free( const_cast<Referent*>( p ) );
}
};
template< class Referent >
class Auto_ptr_
{
public:
typedef void Destruction_func( Referent const* );
private:
Auto_ptr_& operator=( Auto_ptr_ const& ); // No copy assignment.
Auto_ptr_( Auto_ptr_ const& ); // No COPYING via copy constructor.
// A non-const argument copy constructor, for moving, is defined below.
Referent* p_;
Destruction_func* destroy_func_;
static void dummy_destroy_func( Referent const* ) {}
public:
Auto_ptr_ volatile&
as_movable()
{ return const_cast<Auto_ptr_ volatile&>( *this ); }
Referent*
release()
{
Referent* result = p_;
p_ = NULL;
return p_;
}
Referent*
operator->() const
{ return p_; }
Referent&
operator*() const
{ return *p_; }
~Auto_ptr_()
{ destroy_func_( p_ ); }
Auto_ptr_()
: p_( NULL )
, destroy_func_( &dummy_destroy_func )
{}
explicit Auto_ptr_(
Referent* const p,
Destruction_func* const destroy_func = &Destruction_via_delete_<Referent>::destroy
)
: p_( p )
, destroy_func_( destroy_func )
{}
explicit Auto_ptr_(
C_memory_management, // tag
Referent* const p
)
: p_( p )
, destroy_func_( &Destruction_via_free_<Referent>::destroy )
{}
// A C++03 emulation of move constructor; allows return of lvalue.
Auto_ptr_( Auto_ptr_ volatile& other )
: p_( other.p_ )
, destroy_func_( other.destroy_func_ )
{
other.p_ = NULL;
other.destroy_func_ = &dummy_destroy_func;
}
};
} // namespace my
#include <stdio.h>
struct Blah
{
char const* hello() const { return "Hello from Blah-land! :)"; }
~Blah() { printf( "<destroy>\n" ); }
Blah() { printf( "<init>\n" ); }
};
my::Auto_ptr_< Blah >
foo()
{
using namespace my;
Auto_ptr_< Blah > p( c_memory_management, MY_MALLOC( Blah,() ) );
return p.as_movable();
}
void bar( my::Auto_ptr_<Blah> const p )
{
printf( "%s\n", p->hello() );
}
int main()
{
my::Auto_ptr_<Blah> p = foo().as_movable();
printf( "Calling bar()...\n" );
bar( p.as_movable() );
printf( "Returned from bar().\n" );
}
Output:
<init>
Calling bar()...
Hello from Blah-land! :)
<destroy>
Returned from bar().
Disclaimer: I've not written any unit test for the above code, indeed the only testing is what's shown above, that that works. Testing the various cases that one wants this to work for is IMHO necessary for use of this in a production code.

Related

Applying C++11 move semantics to bound functions

I have some existing C++98 code that makes use of boost::function and boost:bind for asynchronous callbacks. Some relevant simplified fragments of the code include:
typedef boost::function<void (boost::system::error_code, size_t)> WriteHandler;
struct WriteOperation
{
WriteOperation(const boost::shared_ptr<IDevice>& device,
const std::string& data, const WriteHandler& handler)
: m_Device(device), m_Data(data), m_Handler(handler) {}
private:
boost::shared_ptr<IDevice> m_Device;
std::string m_Data;
WriteHandler m_Handler;
void Complete()
{
boost::system::error_code ec;
size_t len;
...
Async::Post(boost::bind(m_Handler, ec, len));
}
};
struct Device : public IDevice
{
void Write(const std::string& data, const WriteHandler& callback)
{
...
Async::Start(new WriteOperation(shared_from_this(), data,
boost::bind(&Device::HandleWrite, this, handler, _1, _2)));
}
private:
void HandleWrite(const WriteHandler& callback,
boost::system::error_code ec, size_t len)
{
...
callback(ec, len);
}
};
There is one required copy, when constructing the WriteOperation, but other than that I'm trying to avoid copies since they can be quite expensive.
I'm pondering how this should best be written in the C++11 world. The obvious low-hanging fruit is that the WriteOperation constructor internally copies its arguments to its fields, so should use the automatic copying idiom:
WriteOperation(boost::shared_ptr<IDevice> device,
std::string data, WriteHandler handler)
: m_Device(std::move(device)), m_Data(std::move(data)), m_Handler(std::move(handler))
{}
(And of course the bare new should be replaced with unique_ptr, but that's a side issue.)
However I don't think this actually gains anything given the current implementation of Device::Write, so that ought to change too. My problem is that I don't really see a good way to do it. According to this advice, I have three options:
Declare multiple overloads (one with const& and one with &&) -- but since this has two parameters, both of which could benefit from move semantics, this would require four overloads -- getting exponentially worse for methods with more parameters. Additionally this leads to either code duplication or scattering the code over additional methods, which can impair readability.
Pass by value and move (similar to the WriteOperation constructor). This is perhaps the cleanest option when the body always makes a copy, which is true if the WriteOperation constructor is actually called, but what if the elided section contains logic that might return without constructing a WriteOperation? There's a wasted copy in this case.
Template and perfect forward. This requires an ugly SFINAE hack that confuses Intellisense and impairs readability (or worse, leaving the parameter type unconstrained), and requires that the implementation be put into the header, which is sometimes undesirable. And it interferes with type conversions, eg. a SFINAE enable_if is_same looking for std::string will not accept a const char * literal, while the original const& version will.
Am I missing something? Is there a better solution? Or is this just a case where move semantics don't make any difference?
A related case:
typedef boost::function<void (boost::system::error_code, const std::string&)> ReadHandler;
void Read(const ReadHandler& callback)
{
... boost::bind(&Device::HandleRead, this, callback, _1, _2) ...
}
void HandleRead(const ReadHandler& callback,
boost::system::error_code ec, const std::string& data)
{
...
callback(ec, data);
}
This all seems like it should be ok, with no copying and no need for move semantics. And yet again I'm unsure about the ReadHandler passed to Read.
In rough order:
If copy is just as expensive as move, take it by const&.
If you reliably keep a copy, and move is cheap, take by value.
Failing that, you can stuff it in a header and are ok with sfinae or unconstrained templates, use forwarding references.
Failing that, if there are a limited number of arguments, write each overload. This is 2^n in the number of parameters, so there better not be too many. Forward internally to a forwarding reference based implementation.
Failing that, do you really need efficiency here?
Failing that, type erase to "creator of T".
template<class T, using Base=std::function<T()>>
struct creator_of: Base
{
template<class U,
std::enable_if_t<std::is_constructible<T, U&&>{},int> =0
>
creator_of(U&&u):
Base([&]()->T{ return std::forward<U>(u); })
{}
template<class U,
std::enable_if_t<std::is_constructible<T, std::result_of_t<std::decay_t<U>()>{},int> =0
>
creator_of(U&&u):
Base(std::forward<U>(u))
{}
creator_of(creator_of&&)=default;
creator_of():
Base([]()->T{return {};}}
{}
};
augment as needed. A creator_of<std::string> can be constructed from things that can construct a std::string, or from a function object returning a std::string.
Internally you can call () once on it.
(Code not compiled, but design is sound.)
To avoid the combinatorial explosion, while supporting the case where it turns out inside the called function that no argument copies are needed, you can defer the copying.
That's effectively a lazy evaluation scheme, but for this special case only.
With a support class like the one below one needs to be keenly aware that an instance might just hold a pointer to a short-lived caller's object. I.e., don't move a Lazy_copy_ into storage that outlives the call.
#include <iostream>
#include <new>
#include <string> // std::string
#include <utility> // std::move, std::forward
using namespace std;
//------------------------------------ Machinery:
#ifdef TRACE
inline void trace( string const& s )
{
clog << ": " << s << endl;
}
#else
inline void trace( string const& ) {}
#endif
struct Emplace {};
template< class Item >
class Lazy_copy_
{
private:
Item const* p_callers_item_;
union{ Item item_copy_; }; // Left uninitialized if p_callers_item_.
void ensure_is_copy()
{
if( p_callers_item_ )
{
::new( &item_copy_ ) Item( *p_callers_item_ );
trace( "ensure_is_copy: made copy" );
p_callers_item_ = nullptr;
}
}
public:
auto item() const
-> Item const&
{ return (p_callers_item_? *p_callers_item_ : item_copy_); }
auto item_copy()
-> Item&
{
ensure_is_copy();
return item_copy_;
}
~Lazy_copy_()
{
if( not p_callers_item_ ) { item_copy_.Item::~Item(); }
}
Lazy_copy_( Lazy_copy_ const& other )
: p_callers_item_( other.p_callers_item_ )
{
if( p_callers_item_ )
{
ensure_is_copy();
}
else
{
::new( &item_copy_ ) Item( other.item_copy_ );
trace( "<init>( Lazy_copy ): made copy" );
}
}
Lazy_copy_( Lazy_copy_&& other )
: p_callers_item_( other.p_callers_item_ )
{
if( not p_callers_item_ )
{
::new( &item_copy_ ) Item( move( other.item_copy_ ) );
trace( "<init>( Lazy_copy&& ): moved" );
}
}
Lazy_copy_( Item const& item )
: p_callers_item_( &item )
{}
Lazy_copy_( Item&& temp_item )
: p_callers_item_( nullptr )
, item_copy_( move( temp_item ) )
{
trace( "<init>( Item&& ): moved" );
}
template< class... Args >
Lazy_copy_( Emplace, Args&&... args )
: p_callers_item_( nullptr )
, item_copy_( forward<Args>( args )... )
{
trace( "<init>( Emplace, Args... ): Created item from constructor args" );
}
};
//------------------------------------ Example usage:
struct Thingy
{
string a, b, c;
void foo(
Lazy_copy_<string> arg_one,
Lazy_copy_<string> arg_two,
Lazy_copy_<string> arg_three
)
{
if( arg_one.item() == "no_copy" )
{
return; // The case of no copying needed.
}
a = move( arg_one.item_copy() );
b = move( arg_two.item_copy() );
c = move( arg_three.item_copy() );
}
};
auto main()
-> int
{
Thingy x;
string a = "A", b = "B", c = "C";
trace( "Call with copying:" );
x.foo( string( "a" ), b, c );
trace( "" );
trace( "Call without copying: " );
x.foo( string( "no_copy" ), b, c );
}
Output when built with TRACE defined:
: Call with copying:
: <init>( Item&& ): moved
: ensure_is_copy: made copy
: ensure_is_copy: made copy
:
: Call without copying:
: <init>( Item&& ): moved

const auto && really not useful?

Here
https://youtu.be/dTeKf5Oek2c?t=2939
Stephen T. Lavavej says in a talk that const auto && is not useful.
Isn't the following a valid use case?
NonMovableNonCopyable create () {
// ...
return {};
}
const auto && obj = create ();
Concrete application: In XLL code, MS Excel generally does not like its xlopers to be copied or moved which it returns, since after copying or moving it will not be able to correctly free them.
Instead of
const auto && obj = create ();
... write just
const auto object = create();
... or
const auto object{ create() };
The = relies on the compiler eliding the copy constructor call, but I don't know about any extant compiler that fails to do that.
The clarity gained is IMO much more important than the guarantee offered by the reference (and if using reference, do use an ordinary & reference). Namely, one avoids having a maintenance programmer wasting time on trying to understand the rationale for the reference. If the type was explicitly specified it could be a case of polymorphic reference, Petru Marginean's trick, but with auto that's out of the question, and so the maintenance programmers are left scratching their heads, for some period of paid time.
On the other hand, const T&& can be useful for function overloading as an argument type to catch the case of a temporary as argument, in the same way as && qualifier for member function was considered sufficiently useful to be adopted in the standard. For example, even though I do not recommend this, if a pointer to the actual argument is stored for later use, then presumably one doesn't want to store a pointer to a temporary, which will end up as a dangling pointer:
struct Expr{ virtual ~Expr(){} };
struct Sum_expr: Expr
{
const Expr* a_;
const Expr* b_;
Sum_expr( Expr const& a,Expr const& b ): a_( &a ), b_( &b ) {}
template< class A >
Sum_expr( A&&, Expr const&& b ) = delete;
template< class B >
Sum_expr( Expr const&& a, B&& ) = delete;
};
auto main()
-> int
{
Expr a;
Expr b;
Sum_expr sum{ a, b };
Sum_expr sum2{ a, Expr() }; //! Nope, won't compile.
}
Note: Here A&& and B&& support both rvalue and lvalue actual arguments, i.e. they're not necessarily rvalue references, because they're universal references.
But instead of overloading and differentiating the cases I think I'd make that formal argument a pointer, even if a pointer technically can be a nullpointer, because as I see it, with what I'm accustomed to, it communicates the intent more clearly.
Sum_expr( Expr const* a, Expr const* b );
Const T && is very useful if T has a mutable field. A common example is a bool m_movedFrom that's initialized to false and gets set to true when moved from. This allows the rest of your object - resource handle, for example - to remain const.
class Resource // use this as a base class of const correct classes
{
private:
mutable bool m_movedFrom;
protected:
Resource()
: m_movedFrom(false)
{
}
Resource(const Resource&& other)
: m_movedFrom(false)
{
other.m_movedFrom = true;
}
bool isOwning() const // call from descendant's destructor
{
return m_movedFrom;
}
};
EDIT: a more complicated example explaining when the object is itself const, but a global state is not (not claiming this is the good way to solve this, it's for illustrational purposes only):
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
typedef std::string object_type;
typedef std::string seek_type;
class GoalSeeker
{
private:
static std::vector<const GoalSeeker*> s_store;
const std::vector<const GoalSeeker*>::iterator m_iter;
const object_type m_data;
public:
GoalSeeker( const object_type& data )
: m_iter( s_store.insert( s_store.end(), this ) ), m_data(data)
{
}
GoalSeeker( const GoalSeeker& ) = delete;
GoalSeeker( const GoalSeeker&& other )
: m_iter( other.m_iter ), m_data( other.m_data )
{
*m_iter = this;
}
~GoalSeeker()
{
if( *m_iter == this )
{
// cleanup m_data
}
}
static bool seek( const seek_type& needle )
{
return std::find_if(s_store.begin(), s_store.end(),
[&needle](const GoalSeeker* haystack)
{
return haystack->m_data.find(needle) != std::string::npos;
}) != s_store.end();
}
};
std::vector<const GoalSeeker*> GoalSeeker::s_store = {};
GoalSeeker fn()
{
return GoalSeeker("def");
}
int main() {
GoalSeeker a( "abc" );
GoalSeeker b( "cde" );
GoalSeeker s( (const GoalSeeker&&) fn() );
std::cout << GoalSeeker::seek( "de" ) << " " << GoalSeeker::seek( "fff" );
}

Using unique_ptr to control a file descriptor

In theory, I should be able to use a custom pointer type and deleter in order to have unique_ptr manage an object that is not a pointer. I tried the following code:
#ifndef UNIQUE_FD_H
#define UNIQUE_FD_H
#include <memory>
#include <unistd.h>
struct unique_fd_deleter {
typedef int pointer; // Internal type is a pointer
void operator()( int fd )
{
close(fd);
}
};
typedef std::unique_ptr<int, unique_fd_deleter> unique_fd;
#endif // UNIQUE_FD_H
This doesn't work (gcc 4.7 with the -std=c++11 parameter). It responds with the following errors:
In file included from /usr/include/c++/4.7/memory:86:0,
from test.cc:6:
/usr/include/c++/4.7/bits/unique_ptr.h: In instantiation of 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = int; _Dp = unique_fd_deleter]':
test.cc:22:55: required from here
/usr/include/c++/4.7/bits/unique_ptr.h:172:2: error: invalid operands of types 'int' and 'std::nullptr_t' to binary 'operator!='
From delving into the definition of unique_ptr, I can see two problems that prevent it from working. The first, which seems in clear violation of the standard, is that the destructor for unique_ptr compares the "pointer" (which is, as per my definition, an int) to nullptr in order to see whether it is initialized or not. This is in contrast to the way it reports it through the boolean conversion, which is to compare it to "pointer()" (an uninitialized "pointer"). This is the cause of the errors I am seeing - an integer is not comparable to a nullptr.
The second problem is that I need some way to tell unique_ptr what an uninitialized value is. I want the following snippet to work:
unique_fd fd( open(something...) );
if( !fd )
throw errno_exception("Open failed");
For that to work, unique_ptr needs to know that an "uninitialized value" is -1, as zero is a valid file descriptor.
Is this a bug in gcc, or am I trying to do something here that simply cannot be done?
The type exposed by the Deleter::pointer must satisfy the NullablePointer requirements. Chief among them, this expression must be legal: Deleter::pointer p = nullptr;. Of course, nullptr is pretty much defined by the fact that it cannot be implicitly converted to a number, thus this doesn't work.
You'll have to use a type which can be implicitly constructed with std::nullptr_t. Something like this:
struct file_desc
{
file_desc(int fd) : _desc(fd) {}
file_desc(std::nullptr_t) : _desc(-1) {}
operator int() {return _desc;}
bool operator ==(const file_desc &other) const {return _desc == other._desc;}
bool operator !=(const file_desc &other) const {return _desc != other._desc;}
bool operator ==(std::nullptr_t) const {return _desc == -1;}
bool operator !=(std::nullptr_t) const {return _desc != -1;}
int _desc;
};
You can use that as the Deleter::pointer type.
Can you do something simple like the following?
class unique_fd {
public:
unique_fd(int fd) : fd_(fd) {}
unique_fd(unique_fd&& uf) { fd_ = uf.fd_; uf.fd_ = -1; }
~unique_fd() { if (fd_ != -1) close(fd_); }
explicit operator bool() const { return fd_ != -1; }
private:
int fd_;
unique_fd(const unique_fd&) = delete;
unique_fd& operator=(const unique_fd&) = delete;
};
I do not see why you had to use unique_ptr, which is designed to manage pointers.
Found an answer at cppreference.com.
Look in the examples code:
void close_file(std::FILE* fp) { std::fclose(fp); }
...
{
std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt",
"r"),
&close_file);
if(fp) // fopen could have failed; in which case fp holds a null pointer
std::cout << (char)std::fgetc(fp.get()) << '\n';
}// fclose() called here, but only if FILE* is not a null pointer
// (that is, if fopen succeeded)
Tried it in vs2019 and it works!
Also tried it with member and lambda:
FileTest.h:
class A
{
std::unique_ptr<std::FILE, std::function<void(std::FILE*)>> fp;
}
FileTest.cpp
void A::OpenFile(const char* fname)
{
fp = std::unique_ptr < std::FILE, std::function<void(std::FILE*)>>(
std::fopen(fname, "wb"),
[](std::FILE * fp) { std::fclose(fp); });
}
A complete sample:
#ifdef _MSC_VER
#define _CRT_NONSTDC_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <io.h>
#else
#include <unistd.h>
#endif
#include <memory>
#include <fcntl.h>
template<auto nullvalue, auto delete_>
class unique
{
using T = decltype(nullvalue);
struct generic_delete
{
class pointer
{
T t;
public:
pointer(T t) : t(t) {}
pointer(std::nullptr_t = nullptr) : t(nullvalue) { }
explicit operator bool() { return t != nullvalue; }
friend bool operator ==(pointer lhs, pointer rhs) { return lhs.t == rhs.t; }
friend bool operator !=(pointer lhs, pointer rhs) { return lhs.t != rhs.t; }
operator T() { return t; }
};
void operator()(T p)
{
delete_(p);
}
};
public:
using type = std::unique_ptr<struct not_used, generic_delete>;
};
int main()
{
using unique_fd = unique<-1, close>::type;
static_assert(sizeof(unique_fd) == sizeof(int), "bloated unique_fd");
unique_fd fd1(open("fd.txt", O_WRONLY | O_CREAT | O_TRUNC));
write(fd1.get(), "hello\n", 6);
}
The open source Android Framework defines a unique_fd class that might meet your needs: https://android.googlesource.com/platform/system/core/+/c0e6e40/base/include/android-base/unique_fd.h
Don't coerce a (smart) pointer to be a non-pointer object.
In theory, I should be able to use a custom pointer type and deleter in order to have unique_ptr manage an object that is not a pointer.
No, you should not. That is, in terms of getting it to compile and run, maybe, but you simply shouldn't use a unique_ptr to manage something which is not a pointer. You absolutely should write an appropriate RAII class for your resource - e.g. an OS file descriptor - or use an existing such class from some library. Only if you want a pointer to such a resource does a unique_ptr make sense; but then, you don't need a custom deleter.
Making Nicol Bolas class more general:
template<class T=void*,T null_val=nullptr>
class Handle
{
public:
Handle(T handle):m_handle(handle){}
Handle(std::nullptr_t):m_handle(null_val){}
operator T(){return m_handle;}
bool operator==(const Handle& other) const
{return other.m_handle==m_handle;}
private:
T m_handle;
};
typedef Handle<int,-1> FileDescriptor;
typedef Handle<GLuint,0> GlResource; // according to http://stackoverflow.com/questions/7322147/what-is-the-range-of-opengl-texture-id
// ...
I am not sure if I should have default template parameter values or not.
This solution is based on Nicol Bolas answer:
struct FdDeleter
{
typedef int pointer;
void operator()(int fd)
{
::close(fd);
}
};
typedef std::unique_ptr<int, FdDeleter> UniqueFd;
It's short, but you have to avoid to compare UniqueFd instance with nullptr and use it as boolean expression:
UniqueFd fd(-1, FdDeleter()); //correct
//UniqueFd fd(nullptr, FdDeleter()); //compiler error
if (fd.get() != -1) //correct
{
std::cout << "Ok: it is not printed" << std::endl;
}
if (fd) //incorrect, avoid
{
std::cout << "Problem: it is printed" << std::endl;
}
if (fd != nullptr) //incorrect, avoid
{
std::cout << "Problem: it is printed" << std::endl;
}
return 1;
I would suggest using shared_ptr rather than unique_ptr to manage the life time of int handles because the shared ownership semantics are usually a better fit, and because the type of the deleter is erased. You need the following helper:
namespace handle_detail
{
template <class H, class D>
struct deleter
{
deleter( H h, D d ): h_(h), d_(d) { }
void operator()( H * h ) { (void) d_(h_); }
H h_;
D d_;
};
}
template <class H,class D>
std::shared_ptr<H const>
make_handle( H h, D d )
{
std::shared_ptr<H> p((H *)0,handle_detail::deleter<H,D>(h,d));
return std::shared_ptr<H const>(
p,
&std::get_deleter<handle_detail::deleter<H,D> >(p)->h_ );
}
To use with a file descriptor:
int fh = open("readme.txt", O_RDONLY); // Check for errors though.
std::shared_ptr<int const> f = make_handle(fh, &close);
Boost Core 1.81 introduces boost::fclose_deleter that can be used with something like:
std::unique_ptr<std::FILE, boost::fclose_deleter> make_file(const char* filename, const char* open_mode)
{
return { std::fopen(filename, open_mode) };
}

Selecting between two constructors

Problem: I have a non-copyable object with two constructors. I need to create an object with one of the constructors and then use it within some common code:-
With a copyable object it would look like this, and be easy:
Object a;
if (condition)
a = Object(p1);
else
a = Object(p2,p3,p4);
a.doSomething();
But, the object is non-copyable, so I've had to do this:
boost::scoped_ptr<Object> a;
if (condition)
a = new Object(p1);
else
a = new Object(p2,p3,p4);
a->doSomething();
This feels too complex. Is there a better solutiuon?
Here's a very terrible hack, assuming Object is default-constructible:
Object a;
a.~Object();
if (condition) { ::new (&a) Object(p1); }
else { ::new (&a) Object(p2, p3, p4); }
Don't use this.
Another option is using a union, but you'll need to invoke the destructor manually in that setup as well.
A cleaner solution could be achieved with Boost.Optional (using in-place factories). (Thanks to #K-Ballo for digging up the details!)
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
struct Object
{
explicit Object(int) {}
explicit Object(int, float, std::string) {}
Object(Object const &) = delete;
Object(Object &&) = delete;
Object & operator=(Object const &) = delete;
Object & operator=(Object &&) = delete;
};
boost::optional<Object> a;
if (condition) { a = boost::in_place(0); }
else { a = boost::in_place(0, 1.0f, "two" ); }
Looks perfectly reasonable to me just the way it is. It's clear, simple and relatively concise.
auto const doSomethingTo = []( Object&& o ) { o.doSomething(); };
doSomethingTo( condition? Object( p1 ) : Object( p1, p2, p3 ) );
Disclaimer: code not touched by compiler.
EDIT: the code above, when the Object( Object&& ) constructor is private, fails to compile with MSVC 11.0 (yes even last year's November CTP), but does compile fine with MinGW g++ 4.7.1 and with some version of clang.
It appears that it should compile.
So, it's probably a bug in Visual C++ – but unfortunately I didn't find an easy workaround.
An uneasy workaround for the assumed-to-be Visual C++ compiler bug:
#include <fstream>
#include <iostream>
using namespace std;
class Object
{
private:
Object( Object const& );
Object( Object&& );
public:
void doSomething() const {}
Object( int ) {}
Object( int, int, int ) {}
};
int main( int argc, char* argv[] )
{
int p1 = 0, p2 = 0, p3 = 0;
bool condition = argc == 2;
auto const doSomething1 = [=]() { Object o( p1 ); o.doSomething(); };
auto const doSomething2 = [=]() { Object o( p1, p2, p3 ); o.doSomething(); };
if( condition ) { doSomething1(); } else { doSomething2(); }
}
Another answer maintains that new (read: a dynamic allocation) is your only option.
That's wrong.
There's really nothing wrong with your solution, although as
others have already mentionned, it would be more readably if you
used the conditional operator rather than if's. But you should
consider the possibility of refactoring. If you factor out all
of the code which uses the object into a separate function
(taking the object by reference), then something like:
if ( condition ) {
Object a( p1 );
doWhatever( a );
} else {
Object a( p2, p3, p4 );
doWhatever( a );
}
might be preferable (or not—I don't think that there's any
"right" answer with regards to choosing between these two).
I don't see the complexity... If you need to construct efficiently based on an if-condition declaring a pointer and using new is your only option. What you don't necessarily need to do is:
Use a scoped_ptr (altough that's usually a good idea)
Have the constructor in the if in your "main" code. Yours is a typical use case for a factory (see e.g. http://en.wikipedia.org/wiki/Factory_method_pattern).
EDIT: added "efficiently" in the second sentence.
I think your code is OK.
You just may want to consider the conditional operator ? :
boost::scoped_ptr<Object> a( condition ? new Object(p1) : new Object(p2,p3,p4) );
a->doSomething();
So, here is a quick trick to make this work, without manually constructing objects. Instead, I created a Deferred<T> template that represents an object in automatic storage whose construction is deferred (and possibly never occurs).
The buff in Deferred should be replaced with a union, because that will handle alignment issues (assuming you have C++11 features to support that). Asserts that constructed is true when you call get() is probably a good idea.
Once you have constructed your object, you can implicitly cast your Deferred<T> to a T&, then use that T& as an alias to the deferred-constructed T.
In theory, you could do away with the constructed bool if you could prove that it would always be constructed, but I'd advise against it. Other than that, this should be nearly as efficient as you can pull it off. And with the C++11 union case, it might even be standards compliant.
Oh yes, and it should be enhanced with perfect forwarding.
#include <utility>
// does not handle alignment issues:
template<typename T>
struct Deferred {
Deferred():constructed(false) {}
operator T&() { return get(); }
T& get() { return *reinterpret_cast<T*>(&buff[0]); }
template<typename... Args>
T& construct( Args... args ) {
new(&buff[0]) T(args...);
constructed = true;
return get();
}
~Deferred() {
if (constructed) {
get().~T();
}
}
private:
bool constructed;
char buff[sizeof(T)];
};
#include <iostream>
struct Object {
bool is_int;
Object( int x ):is_int(true) {}
Object( double d ):is_int(false) {}
~Object() {
std::cout << "~Object("<<is_int<<") destroyed\n";
}
};
enum which_test {
as_int,
as_double,
do_not,
};
void test(which_test v) {
std::cout << v << "\n";
Deferred<Object> o;
if(v==as_int) {
o.construct( 7 );
} else if (v==as_double) {
o.construct( 7.0 );
} else {
}
}
int main() {
test(as_int);
test(as_double);
test(do_not);
}

C++ Virtual Constructor, without clone()

I want to perform "deep copies" of an STL container of pointers to polymorphic classes.
I know about the Prototype design pattern, implemented by means of the Virtual Ctor Idiom, as explained in the C++ FAQ Lite, Item 20.8.
It is simple and straightforward:
struct ABC // Abstract Base Class
{
virtual ~ABC() {}
virtual ABC * clone() = 0;
};
struct D1 : public ABC
{
virtual D1 * clone() { return new D1( *this ); } // Covariant Return Type
};
A deep copy is then:
for( i = 0; i < oldVector.size(); ++i )
newVector.push_back( oldVector[i]->clone() );
Drawbacks
As Andrei Alexandrescu states it:
The clone() implementation must follow the same pattern in all derived classes; in spite of its repetitive structure, there is no reasonable way to automate defining the clone() member function (beyond macros, that is).
Moreover, clients of ABC can possibly do something bad. (I mean, nothing prevents clients to do something bad, so, it will happen.)
Better design?
My question is: is there another way to make an abstract base class clonable without requiring derived classes to write clone-related code? (Helper class? Templates?)
Following is my context. Hopefully, it will help understanding my question.
I am designing a class hierarchy to perform operations on a class Image:
struct ImgOp
{
virtual ~ImgOp() {}
bool run( Image & ) = 0;
};
Image operations are user-defined: clients of the class hierarchy will implement their own classes derived from ImgOp:
struct CheckImageSize : public ImgOp
{
std::size_t w, h;
bool run( Image &i ) { return w==i.width() && h==i.height(); }
};
struct CheckImageResolution { ... };
struct RotateImage { ... };
...
Multiple operations can be performed sequentially on an image:
bool do_operations( vector< ImgOp* > v, Image &i )
{
for_each( v.begin(), v.end(),
/* bind2nd( mem_fun( &ImgOp::run ), i ... ) don't remember syntax */ );
}
If there are multiple images, the set can be split and shared over several threads. To ensure "thread-safety", each thread must have its own copy of all operation objects contained in v -- v becomes a prototype to be deep copied in each thread.
Edited: The thread-safe version uses the Prototype design pattern to enforce copy of pointed-to-objects -- not ptrs:
struct ImgOp
{
virtual ~ImgOp() {}
bool run( Image & ) = 0;
virtual ImgOp * clone() = 0; // virtual ctor
};
struct CheckImageSize : public ImgOp { /* no clone code */ };
struct CheckImageResolution : public ImgOp { /* no clone code */ };
struct RotateImage : public ImgOp { /* no clone code */ };
bool do_operations( vector< ImgOp* > v, Image &i )
{
// In another thread
vector< ImgOp* > v2;
transform( v.begin(), v.end(), // Copy pointed-to-
back_inserter( v2 ), mem_fun( &ImgOp::clone ) ); // objects
for_each( v.begin(), v.end(),
/* bind2nd( mem_fun( &ImgOp::run ), i ... ) don't remember syntax */ );
}
This has sense when image operation classes are small: do not serialize accesses to unique instances of ImgOps, rather provide each thread with their own copies.
The hard part is to avoid writers of new ImgOp-derived classes to write any clone-related code. (Because this is implementation detail -- this is why I dismissed Paul's answers with the Curiously Recurring Pattern.)
You can use the curiously recursive pattern but it might make your code less readable.
You will still need copy constructors. It works as follows.
struct ABC // Abstract Base Class
{
virtual ~ABC() {}
virtual ABC * clone() const = 0;
};
template <class TCopyableClass>
struct ClonableABC : public ABC
{
virtual ABC* clone() const {
return new TCopyableClass( *(TCopyableClass*)this );
}
};
struct SomeABCImpl : public ClonableABC<SomeABCImpl>
{};
A deep copy is then: [for loop]
You make the client clone the vector explicitly. I'm not sure if this answers your question, but I would suggest a vector of smart pointers so the cloning happens automatically.
std::vector<cloning_pointer<Base> > vec;
vec.push_back(cloning_pointer<Base>(new Derived()));
// objects are automatically cloned:
std::vector<cloning_pointer<Base> > vec2 = vec;
Of course, you don't want these implicit copies to happen when resizing a vector or something, so you need to be able to distinguish copies from moves. Here is my C++0x toy implementation of cloning_pointer which you might have to adjust to your needs.
#include <algorithm>
template<class T>
class cloning_pointer
{
T* p;
public:
explicit cloning_pointer(T* p)
{
this->p = p;
}
~cloning_pointer()
{
delete p;
}
cloning_pointer(const cloning_pointer& that)
{
p = that->clone();
}
cloning_pointer(cloning_pointer&& that)
{
p = that.p;
that.p = 0;
}
cloning_pointer& operator=(const cloning_pointer& that)
{
T* q = that->clone();
delete p;
p = q;
return *this;
}
cloning_pointer& operator=(cloning_pointer&& that)
{
std::swap(p, that.p);
return *this;
}
T* operator->() const
{
return p;
}
T& operator*() const
{
return *p;
}
};
Julien: && is not a "ref of ref", it is an rvalue reference which only binds to modifiable rvalues. See this excellent (but sadly slightly outdated) tutorial and video for an overview of rvalue references and how they work.
FYI, this is the design I came out with. Thank you Paul and FredOverflow for your inputs. (And Martin York for your comment.)
Step #1, Compile-time polymorphism with templates
Polymorphism is performed at compile-time using templates and implicit-interfaces:
template< typename T >
class ImgOp
{
T m_t; // Not a ptr: when ImgOp is copied, copy ctor and
// assignement operator perform a *real* copy of object
ImageOp ( const ImageOp &other ) : m_t( other .m_t ) {}
ImageOp & operator=( const ImageOp & );
public:
ImageOp ( const T &p_t ) : m_t( p_t ) {}
ImageOp<T> * clone() const { return new ImageOp<T>( *this ); }
bool run( Image &i ) const { return m_t.run( i); }
};
// Image operations need not to derive from a base class: they must provide
// a compatible interface
class CheckImageSize { bool run( Image &i ) const {...} };
class CheckImageResolution { bool run( Image &i ) const {...} };
class RotateImage { bool run( Image &i ) const {...} };
Now all the clone-related code lies within a unique class. However, it is now impossible to have a container of ImgOps templatized on different operations:
vector< ImgOp > v; // Compile error, ImgOp is not a type
vector< ImgOp< ImgOp1 > > v; // Only one type of operation :/
Step #2, Add a level of abstraction
Add a non-template base acting as an interface:
class AbstractImgOp
{
ImageOp<T> * clone() const = 0;
bool run( Image &i ) const = 0;
};
template< typename T >
class ImgOp : public AbstractImgOp
{
// No modification, especially on the clone() method thanks to
// the Covariant Return Type mechanism
};
Now we can write:
vector< AbstractImgOp* > v;
But it becomes hard to manipulate image operation objects:
AbstractImgOp *op1 = new AbstractImgOp;
op1->w = ...; // Compile error, AbstractImgOp does not have
op2->h = ...; // member named 'w' or 'h'
CheckImageSize *op1 = new CheckImageSize;
op1->w = ...; // Fine
op1->h = ...;
AbstractImgOp *op1Ptr = op1; // Compile error, CheckImageSize does not derive
// from AbstractImgOp? Confusing
CheckImageSize op1;
op1.w = ...; // Fine
op1.h = ...;
CheckImageResolution op2;
// ...
v.push_back( new ImgOp< CheckImageSize >( op1 ) ); // Confusing!
v.push_back( new ImgOp< CheckImageResolution >( op2 ) ); // Argh
Step #3, Add a "cloning pointer" class
Based on the FredOverflow's solution, make a cloning pointer to make the framework simpler to use.
However, this pointer needs not to be templatized for it is designed to hold only one type of ptr -- only the ctor needs to be templatized:
class ImgOpCloner
{
AbstractImgOp *ptr; // Ptr is mandatory to achieve polymorphic behavior
ImgOpCloner & operator=( const ImgOpCloner & );
public:
template< typename T >
ImgOpCloner( const T &t ) : ptr( new ImgOp< T >( t ) ) {}
ImgOpCloner( const AbstractImgOp &other ) : ptr( other.ptr->clone() ) {}
~ImgOpCloner() { delete ptr; }
AbstractImgOp * operator->() { return ptr; }
AbstractImgOp & operator*() { return *ptr; }
};
Now we can write:
CheckImageSize op1;
op1.w = ...; // Fine
op1.h = ...;
CheckImageResolution op2;
// ...
vector< ImgOpCloner > v;
v.push_back( ImgOpCloner( op1 ) ); // This looks like a smart-ptr, this is not
v.push_back( ImgOpCloner( op2 ) ); // confusing anymore -- and intent is clear