Search Results

Search found 21 results on 1 pages for 'noncopyable'.

Page 1/1 | 1 

  • noncopyable static const member class in template class

    - by Dukales
    I have a non-copyable (inherited from boost::noncopyable) class that I use as a custom namespace. Also, I have another class, that uses previous one, as shown here: #include <boost/utility.hpp> #include <cmath> template< typename F > struct custom_namespace : boost::noncopyable { F sqrt_of_half(F const & x) const { using std::sqrt; return sqrt(x / F(2.0L)); } // ... maybe others are not so dummy const/constexpr methods }; template< typename F > class custom_namespace_user { static ::custom_namespace< F > const custom_namespace_; public : F poisson() const { return custom_namespace_.sqrt_of_half(M_PI); } static F square_diagonal(F const & a) { return a * custom_namespace_.sqrt_of_half(1.0L); } }; template< typename F > ::custom_namespace< F > const custom_namespace_user< F >::custom_namespace_(); this code leads to the next error (even without instantiation): error: no 'const custom_namespace custom_namespace_user::custom_namespace_()' member function declared in class 'custom_namespace_user' The next way is not legitimate: template< typename F ::custom_namespace< F const custom_namespace_user< F ::custom_namespace_ = ::custom_namespace< F (); What should I do to declare this two classes (first as noncopyable static const member class of second)? Is this feaseble?

    Read the article

  • Is it good practice to generally make heavyweight classes non-copyable?

    - by Emile Cormier
    I have a Shape class containing potentially many vertices, and I was contemplating making copy-constructor/copy-assignment private to prevent accidental needless copying of my heavyweight class (for example, passing by value instead of by reference). To make a copy of Shape, one would have to deliberately call a "clone" or "duplicate" method. Is this good practice? I wonder why STL containers don't use this approach, as I rarely want to pass them by value.

    Read the article

  • Is it a good idea to create an STL iterator which is noncopyable?

    - by BillyONeal
    Most of the time, STL iterators are CopyConstructable, because several STL algorithms require this to improve performance, such as std::sort. However, I've been working on a pet project to wrap the FindXFile API (previously asked about), but the problem is it's impossible to implement a copyable iterator around this API. A find handle cannot be duplicated by any means -- DuplicateHandle specifically forbids passing handles to it. And if you just maintain a reference count to the find handle, then a single increment by any copy results in an increment of all copies -- clearly that is not what a copy constructed iterator is supposed to do. Since I can't satisfy the traditional copy constructible requirement for iterators here, is it even worth trying to create an "STL style" iterator? On one hand, creating some other enumeration method is going to not fall into normal STL conventions, but on the other, following STL conventions are going to confuse users of this iterator if they try to CopyConstruct it later. Which is the lesser of two evils?

    Read the article

  • non-copyable objects and value initialization: g++ vs msvc

    - by R Samuel Klatchko
    I'm seeing some different behavior between g++ and msvc around value initializing non-copyable objects. Consider a class that is non-copyable: class noncopyable_base { public: noncopyable_base() {} private: noncopyable_base(const noncopyable_base &); noncopyable_base &operator=(const noncopyable_base &); }; class noncopyable : private noncopyable_base { public: noncopyable() : x_(0) {} noncopyable(int x) : x_(x) {} private: int x_; }; and a template that uses value initialization so that the value will get a known value even when the type is POD: template <class T> void doit() { T t = T(); ... } and trying to use those together: doit<noncopyable>(); This works fine on msvc as of VC++ 9.0 but fails on every version of g++ I tested this with (including version 4.5.0) because the copy constructor is private. Two questions: Which behavior is standards compliant? Any suggestion of how to work around this in gcc (and to be clear, changing that to T t; is not an acceptable solution as this breaks POD types). P.S. I see the same problem with boost::noncopyable.

    Read the article

  • Storing objects in the array

    - by Ockonal
    Hello, I want to save boost signals objects in the map (association: signal name ? signal object). The signals signature is different, so the second type of map should be boost::any. map<string, any> mSignalAssociation; The question is how to store objects without defining type of new signal signature? typedef boost::signals2::signal<void (int KeyCode)> sigKeyPressed; mSignalAssociation.insert(make_pair("KeyPressed", sigKeyPressed())); // This is what I need: passing object without type definition mSignalAssociation["KeyPressed"] = (typename boost::signals2::signal<void (int KeyCode)>()); // One more trying which won't work. And I don't want use this sigKeyPressed mKeyPressed; mSignalAssociation["KeyPressed"] = mKeyPressed; All this tryings throw the error: /usr/include/boost/noncopyable.hpp: In copy constructor ‘boost::signals2::signal_base::signal_base(const boost::signals2::signal_base&)’: In file included from /usr/include/boost/signals2/detail/signals_common.hpp:17:0, /usr/include/boost/noncopyable.hpp:27:7: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private /usr/include/boost/signals2/signal_base.hpp:22:5: error: within this context ---------- /usr/include/boost/signals2/detail/signal_template.hpp: In copy constructor ‘boost::signals2::signal1<void, int&, boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void(int)>, boost::function<void(const boost::signals2::connection&, int)>, boost::signals2::mutex>::signal1(const boost::signals2::signal1<void, int, boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void(int)>, boost::function<void(const boost::signals2::connection&, int)>, boost::signals2::mutex>&)’: In file included from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52:0, /usr/include/boost/signals2/detail/signal_template.hpp:578:5: note: synthesized method ‘boost::signals2::signal_base::signal_base(const boost::signals2::signal_base&)’ first required here from /usr/include/boost/signals2.hpp:16, --------- /usr/include/boost/signals2/preprocessed_signal.hpp: In copy constructor ‘boost::signals2::signal<void(int)>::signal(const boost::signals2::signal<void(int)>&)’: In file included from /usr/include/boost/signals2/signal.hpp:36:0, /usr/include/boost/signals2/preprocessed_signal.hpp:42:5: note: synthesized method ‘boost::signals2::signal1<void, int, boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void(int)>, boost::function<void(const boost::signals2::connection&, int)>, boost::signals2::mutex>::signal1(const boost::signals2::signal1<void, int, boost::signals2::optional_last_value<void>, int, std::less<int>, boost::function<void(int)>, boost::function<void(const boost::signals2::connection&, int)>, boost::signals2::mutex>&)’ first required here from /home/ockonal/Workspace/Projects/Pseudoform-2/include/Core/Systems.hpp:6,

    Read the article

  • Init var without copy constructor

    - by Ockonal
    Hello, I have some class(Window) without copy constructor (it's private). I can't understand how to init var of this class in my own class: class MyClass { Window obj; // Hasn't copy constructor public: void init() { obj = Window(/* constructor params */); // [error] obj(/* constructor params */); // [error] } } Error 1: initializing argument 1 of ‘Window::Window(WindowHandle, const sf::WindowSettings&)’ Error 2: ‘NonCopyable& NonCopyable::operator=(const NonCopyable&)’ is private But it works in this way: Window obj(/* constructor params */);

    Read the article

  • Wrapping a pure virtual method with multiple arguments with Boost.Python

    - by fallino
    Hello, I followed the "official" tutorial and others but still don't manage to expose this pure virtual method (getPeptide) : ms_mascotresults.hpp class ms_mascotresults { public: ms_mascotresults(ms_mascotresfile &resfile, const unsigned int flags, double minProbability, int maxHitsToReport, const char * unigeneIndexFile, const char * singleHit = 0); ... virtual ms_peptide getPeptide(const int q, const int p) const = 0; } ms_mascotresults.cpp #include <boost/python.hpp> using namespace boost::python; #include "msparser.hpp" // which includes "ms_mascotresults.hpp" using namespace matrix_science; #include <iostream> #include <sstream> struct ms_mascotresults_wrapper : ms_mascotresults, wrapper<ms_mascotresults> { ms_peptide getPeptide(const int q, const int p) { this->get_override("getPeptide")(q); this->get_override("getPeptide")(p); } }; BOOST_PYTHON_MODULE(ms_mascotresults) { class_<ms_mascotresults_wrapper, boost::noncopyable>("ms_mascotresults") .def("getPeptide", pure_virtual(&ms_mascotresults::getPeptide) ) ; } Here are the bjam's errors : /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp:66: error: cannot declare field ‘boost::python::objects::value_holder<ms_mascotresults_wrapper>::m_held’ to be of abstract type ‘ms_mascotresults_wrapper’ ms_mascotresults.cpp:12: note: because the following virtual functions are pure within ‘ms_mascotresults_wrapper’: ... include/ms_mascotresults.hpp:334: note: virtual matrix_science::ms_peptide matrix_science::ms_mascotresults::getPeptide(int, int) const ms_mascotresults.cpp: In constructor ‘ms_mascotresults_wrapper::ms_mascotresults_wrapper()’: ms_mascotresults.cpp:12: error: no matching function for call to ‘matrix_science::ms_mascotresults::ms_mascotresults()’ include/ms_mascotresults.hpp:284: note: candidates are: matrix_science::ms_mascotresults::ms_mascotresults(matrix_science::ms_mascotresfile&, unsigned int, double, int, const char*, const char*) include/ms_mascotresults.hpp:109: note: matrix_science::ms_mascotresults::ms_mascotresults(const matrix_science::ms_mascotresults&) ... /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp: In constructor ‘boost::python::objects::value_holder<Value>::value_holder(PyObject*) [with Value = ms_mascotresults_wrapper]’: /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp:137: note: synthesized method ‘ms_mascotresults_wrapper::ms_mascotresults_wrapper()’ first required here /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp:137: error: cannot allocate an object of abstract type ‘ms_mascotresults_wrapper’ ms_mascotresults.cpp:12: note: since type ‘ms_mascotresults_wrapper’ has pure virtual functions So I tried to change the constructor's signature by : BOOST_PYTHON_MODULE(ms_mascotresults) { //class_<ms_mascotresults_wrapper, boost::noncopyable>("ms_mascotresults") class_<ms_mascotresults_wrapper, boost::noncopyable>("ms_mascotresults", init<ms_mascotresfile &, const unsigned int, double, int, const char *,const char *>()) .def("getPeptide", pure_virtual(&ms_mascotresults::getPeptide) ) Giving these errors : /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp:66: error: cannot declare field ‘boost::python::objects::value_holder<ms_mascotresults_wrapper>::m_held’ to be of abstract type ‘ms_mascotresults_wrapper’ ms_mascotresults.cpp:12: note: because the following virtual functions are pure within ‘ms_mascotresults_wrapper’: include/ms_mascotresults.hpp:334: note: virtual matrix_science::ms_peptide matrix_science::ms_mascotresults::getPeptide(int, int) const ... ms_mascotresults.cpp:24: instantiated from here /usr/local/boost_1_42_0/boost/python/object/value_holder.hpp:137: error: no matching function for call to ‘ms_mascotresults_wrapper::ms_mascotresults_wrapper(matrix_science::ms_mascotresfile&, const unsigned int&, const double&, const int&, const char* const&, const char* const&)’ ms_mascotresults.cpp:12: note: candidates are: ms_mascotresults_wrapper::ms_mascotresults_wrapper(const ms_mascotresults_wrapper&) ms_mascotresults.cpp:12: note: ms_mascotresults_wrapper::ms_mascotresults_wrapper() If I comment the virtual function getPeptide in the .hpp, it builds perfectly with this constructor : class_<ms_mascotresults>("ms_mascotresults", init<ms_mascotresfile &, const unsigned int, double, int, const char *,const char *>() ) So I'm a bit lost...

    Read the article

  • Is there a way to increase the efficiency of shared_ptr by storing the reference count inside the co

    - by BillyONeal
    Hello everyone :) This is becoming a common pattern in my code, for when I need to manage an object that needs to be noncopyable because either A. it is "heavy" or B. it is an operating system resource, such as a critical section: class Resource; class Implementation : public boost::noncopyable { friend class Resource; HANDLE someData; Implementation(HANDLE input) : someData(input) {}; void SomeMethodThatActsOnHandle() { //Do stuff }; public: ~Implementation() { FreeHandle(someData) }; }; class Resource { boost::shared_ptr<Implementation> impl; public: Resource(int argA) explicit { HANDLE handle = SomeLegacyCApiThatMakesSomething(argA); if (handle == INVALID_HANDLE_VALUE) throw SomeTypeOfException(); impl.reset(new Implementation(handle)); }; void SomeMethodThatActsOnTheResource() { impl->SomeMethodThatActsOnTheHandle(); }; }; This way, shared_ptr takes care of the reference counting headaches, allowing Resource to be copyable, even though the underlying handle should only be closed once all references to it are destroyed. However, it seems like we could save the overhead of allocating shared_ptr's reference counts and such separately if we could move that data inside Implementation somehow, like boost's intrusive containers do. If this is making the premature optimization hackles nag some people, I actually agree that I don't need this for my current project. But I'm curious if it is possible.

    Read the article

  • Resource allocation and automatic deallocation

    - by nabulke
    In my application I got many instances of class CDbaOciNotifier. They all share a pointer to only one instance of class OCIEnv. What I like to achieve is that allocation and deallocation of the resource class OCIEnv will be handled automatically inside class CDbaOciNotifier. The desired behaviour is, with the first instance of class CDbaOciNotifier the environment will be created, after that all following notifiers use that same environment. With the destruction of the last notifier, the environment will be destroyed too (call to custom deleter). What I've got so far (using a static factory method to create notifiers): #pragma once #include <string> #include <memory> #include "boost\noncopyable.hpp" class CDbaOciNotifier : private boost::noncopyable { public: virtual ~CDbaOciNotifier(void); static std::auto_ptr<CDbaOciNotifier> createNotifier(const std::string &tnsName, const std::string &user, const std::string &password); private: CDbaOciNotifier(OCIEnv* envhp); // All notifiers share one environment static OCIEnv* m_ENVHP; // Custom deleter static void freeEnvironment(OCIEnv *env); OCIEnv* m_envhp; }; CPP: #include "DbaOciNotifier.h" using namespace std; OCIEnv* CDbaOciNotifier::m_ENVHP = 0; CDbaOciNotifier::~CDbaOciNotifier(void) { } CDbaOciNotifier::CDbaOciNotifier(OCIEnv* envhp) :m_envhp(envhp) { } void CDbaOciNotifier::freeEnvironment(OCIEnv *env) { OCIHandleFree((dvoid *) env, (ub4) OCI_HTYPE_ENV); *env = null; } auto_ptr<CDbaOciNotifier> CDbaOciNotifier::createNotifier(const string &tnsName, const string &user, const string &password) { if(!m_ENVHP) { OCIEnvCreate( (OCIEnv **) &m_ENVHP, OCI_EVENTS|OCI_OBJECT, (dvoid *)0, (dvoid * (*)(dvoid *, size_t)) 0, (dvoid * (*)(dvoid *, dvoid *, size_t))0, (void (*)(dvoid *, dvoid *)) 0, (size_t) 0, (dvoid **) 0 ); } //shared_ptr<OCIEnv> spEnvhp(m_ENVHP, freeEnvironment); ...got so far... return auto_ptr<CDbaOciNotifier>(new CDbaOciNotifier(m_ENVHP)); } I'd like to avoid counting references (notifiers) myself, and use something like shared_ptr. Do you see an easy solution to my problem?

    Read the article

  • Is this an idiomatic way to pass mocks into objects?

    - by Billy ONeal
    I'm a bit confused about passing in this mock class into an implementation class. It feels wrong to have all this explicitly managed memory flying around. I'd just pass the class by value but that runs into the slicing problem. Am I missing something here? Implementation: namespace detail { struct FileApi { virtual HANDLE CreateFileW( __in LPCWSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile ) { return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } virtual void CloseHandle(HANDLE handleToClose) { ::CloseHandle(handleToClose); } }; } class File : boost::noncopyable { HANDLE hWin32; boost::scoped_ptr<detail::FileApi> fileApi; public: File( __in LPCWSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile, __in detail::FileApi * method = new detail::FileApi() ) { fileApi.reset(method); hWin32 = fileApi->CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } }; namespace detail { struct FileApi { virtual HANDLE CreateFileW( __in LPCWSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile ) { return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } virtual void CloseHandle(HANDLE handleToClose) { ::CloseHandle(handleToClose); } }; } class File : boost::noncopyable { HANDLE hWin32; boost::scoped_ptr<detail::FileApi> fileApi; public: File( __in LPCWSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile, __in detail::FileApi * method = new detail::FileApi() ) { fileApi.reset(method); hWin32 = fileApi->CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } ~File() { fileApi->CloseHandle(hWin32); } }; Tests: namespace detail { struct MockFileApi : public FileApi { MOCK_METHOD7(CreateFileW, HANDLE(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE)); MOCK_METHOD1(CloseHandle, void(HANDLE)); }; } using namespace detail; using namespace testing; TEST(Test_File, OpenPassesArguments) { MockFileApi * api = new MockFileApi; EXPECT_CALL(*api, CreateFileW(Eq(L"BozoFile"), Eq(56), Eq(72), Eq(reinterpret_cast<LPSECURITY_ATTRIBUTES>(67)), Eq(98), Eq(102), Eq(reinterpret_cast<HANDLE>(98)))) .Times(1).WillOnce(Return(reinterpret_cast<HANDLE>(42))); File test(L"BozoFile", 56, 72, reinterpret_cast<LPSECURITY_ATTRIBUTES>(67), 98, 102, reinterpret_cast<HANDLE>(98), api); }

    Read the article

  • Boost any usage

    - by Ockonal
    Hello, how can I insert my own class objects into ptr_map from boost. The objects are templated so I can't use some static typename in the map. So I did: ptr_map<string, any> someMap; My class inherits the boost::noncopyable. someMap.insert("Test", new MyClass()); The error is: error: no matching function for call to ‘boost::ptr_map.

    Read the article

  • Is this too much code for a header only library?

    - by Billy ONeal
    It seems like I had to inline quite a bit of code here. I'm wondering if it's bad design practice to leave this entirely in a header file like this: #pragma once #include <string> #include <boost/noncopyable.hpp> #include <boost/make_shared.hpp> #include <boost/iterator/iterator_facade.hpp> #include <Windows.h> #include "../Exception.hpp" namespace WindowsAPI { namespace FileSystem { class FileData; struct AllResults; struct FilesOnly; template <typename Filter_T = AllResults> class DirectoryIterator; namespace detail { class DirectoryIteratorImpl : public boost::noncopyable { WIN32_FIND_DATAW currentData; HANDLE hFind; std::wstring root; public: inline DirectoryIteratorImpl(); inline explicit DirectoryIteratorImpl(const std::wstring& pathSpec); inline void increment(); inline bool equal(const DirectoryIteratorImpl& other) const; inline const std::wstring& GetPathRoot() const; inline const WIN32_FIND_DATAW& GetCurrentFindData() const; inline ~DirectoryIteratorImpl(); }; } class FileData //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator. { boost::shared_ptr<detail::DirectoryIteratorImpl> iteratorSource; public: FileData(const boost::shared_ptr<detail::DirectoryIteratorImpl>& parent) : iteratorSource(parent) {}; DWORD GetAttributes() const { return iteratorSource->GetCurrentFindData().dwFileAttributes; }; bool IsDirectory() const { return (GetAttributes() | FILE_ATTRIBUTE_DIRECTORY) != 0; }; bool IsFile() const { return !IsDirectory(); }; bool IsArchive() const { return (GetAttributes() | FILE_ATTRIBUTE_ARCHIVE) != 0; }; bool IsReadOnly() const { return (GetAttributes() | FILE_ATTRIBUTE_READONLY) != 0; }; unsigned __int64 GetSize() const { ULARGE_INTEGER intValue; intValue.LowPart = iteratorSource->GetCurrentFindData().nFileSizeLow; intValue.HighPart = iteratorSource->GetCurrentFindData().nFileSizeHigh; return intValue.QuadPart; }; std::wstring GetFolderPath() const { return iteratorSource->GetPathRoot(); }; std::wstring GetFileName() const { return iteratorSource->GetCurrentFindData().cFileName; }; std::wstring GetFullFileName() const { return GetFolderPath() + GetFileName(); }; std::wstring GetShortFileName() const { return iteratorSource->GetCurrentFindData().cAlternateFileName; }; FILETIME GetCreationTime() const { return iteratorSource->GetCurrentFindData().ftCreationTime; }; FILETIME GetLastAccessTime() const { return iteratorSource->GetCurrentFindData().ftLastAccessTime; }; FILETIME GetLastWriteTime() const { return iteratorSource->GetCurrentFindData().ftLastWriteTime; }; }; struct AllResults : public std::unary_function<const FileData&, bool> { bool operator()(const FileData&) { return true; }; }; struct FilesOnly : public std::unary_function<const FileData&, bool> { bool operator()(const FileData& arg) { return arg.IsFile(); }; }; template <typename Filter_T> class DirectoryIterator : public boost::iterator_facade<DirectoryIterator<Filter_T>, const FileData, std::input_iterator_tag> { friend class boost::iterator_core_access; boost::shared_ptr<detail::DirectoryIteratorImpl> impl; FileData current; Filter_T filter; void increment() { do { impl->increment(); } while (! filter(current)); }; bool equal(const DirectoryIterator& other) const { return impl->equal(*other.impl); }; const FileData& dereference() const { return current; }; public: DirectoryIterator(Filter_T functor = Filter_T()) : impl(boost::make_shared<detail::DirectoryIteratorImpl>()), current(impl), filter(functor) { }; explicit DirectoryIterator(const std::wstring& pathSpec, Filter_T functor = Filter_T()) : impl(boost::make_shared<detail::DirectoryIteratorImpl>(pathSpec)), current(impl), filter(functor) { }; }; namespace detail { DirectoryIteratorImpl::DirectoryIteratorImpl() : hFind(INVALID_HANDLE_VALUE) { } DirectoryIteratorImpl::DirectoryIteratorImpl(const std::wstring& pathSpec) { std::wstring::const_iterator lastSlash = std::find(pathSpec.rbegin(), pathSpec.rend(), L'\\').base(); root.assign(pathSpec.begin(), lastSlash); hFind = FindFirstFileW(pathSpec.c_str(), &currentData); if (hFind == INVALID_HANDLE_VALUE) WindowsApiException::ThrowFromLastError(); while (!wcscmp(currentData.cFileName, L".") || !wcscmp(currentData.cFileName, L"..")) { increment(); } } void DirectoryIteratorImpl::increment() { BOOL success = FindNextFile(hFind, &currentData); if (success) return; DWORD error = GetLastError(); if (error == ERROR_NO_MORE_FILES) { FindClose(hFind); hFind = INVALID_HANDLE_VALUE; } else { WindowsApiException::Throw(error); } } DirectoryIteratorImpl::~DirectoryIteratorImpl() { if (hFind != INVALID_HANDLE_VALUE) FindClose(hFind); } bool DirectoryIteratorImpl::equal(const DirectoryIteratorImpl& other) const { if (this == &other) return true; return hFind == other.hFind; } const std::wstring& DirectoryIteratorImpl::GetPathRoot() const { return root; } const WIN32_FIND_DATAW& DirectoryIteratorImpl::GetCurrentFindData() const { return currentData; } } }}

    Read the article

  • Using the Proxy pattern with C++ iterators

    - by Billy ONeal
    Hello everyone :) I've got a moderately complex iterator written which wraps the FindXFile apis on Win32. (See previous question) In order to avoid the overhead of constructing an object that essentially duplicates the work of the WIN32_FIND_DATAW structure, I have a proxy object which simply acts as a sort of const reference to the single WIN32_FIND_DATAW which is declared inside the noncopyable innards of the iterator. This is great because Clients do not pay for construction of irrelevant information they will probably not use (most of the time people are only interested in file names), and Clients can get at all the information provided by the FindXFile APIs if they need or want this information. This becomes an issue though because there is only ever a single copy of the object's actual data. Therefore, when the iterator is incrememnted, all of the proxies are invalidated (set to whatever the next file pointed to by the iterator is). I'm concerned if this is a major problem, because I can think of a case where the proxy object would not behave as somebody would expect: std::vector<MyIterator::value_type> files; std::copy(MyIterator("Hello"), MyIterator(), std::back_inserter(files)); because the vector contains nothing but a bunch of invalid proxies at that point. Instead, clients need to do something like: std::vector<std::wstring> filesToSearch; std::transform( DirectoryIterator<FilesOnly>(L"C:\\Windows\\*"), DirectoryIterator<FilesOnly>(), std::back_inserter(filesToSearch), std::mem_fun_ref(&DirectoryIterator<FilesOnly>::value_type::GetFullFileName) ); Seeing this, I can see why somebody might dislike what the standard library designers did with std::vector<bool>. I'm still wondering though: is this a reasonable trade off in order to achieve (1) and (2) above? If not, is there any way to still achieve (1) and (2) without the proxy?

    Read the article

  • Immutable classes in C++

    - by ereOn
    Hi, In one of my projects, I have some classes that represent entities that cannot change once created, aka. immutable classes. Example : A class RSAKey that represent a RSA key which only has const methods. There is no point changing the existing instance: if you need another one, you just create one. My objects sometimes are heavy and I enforced the use of smart pointers to avoid copy. So far, I have the following pattern for my classes: class RSAKey : public boost::noncopyable, public boost::enable_shared_from_this<RSAKey> { public: /** * \brief Some factory. * \param member A member value. * \return An instance. */ static boost::shared_ptr<const RSAKey> createFromMember(int member); /** * \brief Get a member. * \return The member. */ int getMember() const; private: /** * \brief Constructor. * \param member A member. */ RSAKey(int member); /** * \brief Member. */ const int m_member; }; So you can only get a pointer (well, a smart pointer) to a const RSAKey. To me, it makes sense, because having a non-const reference to the instance is useless (it only has const methods). Do you guys see any issue regarding this pattern ? Are immutable classes something common in C++ or did I just created a monster ? Thank you for your advices !

    Read the article

  • how to emulate thread local storage at user space in C++ ?

    - by vprajan
    I am working on a mobile platform over Nucleus RTOS. It uses Nucleus Threading system but it doesn't have support for explicit thread local storage i.e, TlsAlloc, TlsSetValue, TlsGetValue, TlsFree APIs. The platform doesn't have user space pthreads as well. I found that __thread storage modifier is present in most of the C++ compilers. But i don't know how to make it work for my kind of usage. How does __thread keyword can be mapped with explicit thread local storage? I read many articles but nothing is so clear for giving me the following basic information will __thread variable different for each thread ? How to write to that and read from it ? does each thread has exactly one copy of the variable ? following is the pthread based implementation: pthread_key_t m_key; struct Data : Noncopyable { Data(T* value, void* owner) : value(value), owner(owner) {} int* value; }; inline ThreadSpecific() { int error = pthread_key_create(&m_key, destroy); if (error) CRASH(); } inline ~ThreadSpecific() { pthread_key_delete(m_key); // Does not invoke destructor functions. } inline T* get() { Data* data = static_cast<Data*>(pthread_getspecific(m_key)); return data ? data->value : 0; } inline void set(T* ptr) { ASSERT(!get()); pthread_setspecific(m_key, new Data(ptr, this)); } How to make the above code use __thread way to set & get specific value ? where/when does the create & delete happen? If this is not possible, how to write custom pthread_setspecific, pthread_getspecific kind of APIs. I tried using a C++ global map and index it uniquely for each thread and retrieved data from it. But it didn't work well.

    Read the article

  • Member function overloading/template specialization issue

    - by Ferruccio
    I've been trying to call the overloaded table::scan_index(std::string, ...) member function without success. For the sake of clarity, I have stripped out all non-relevant code. I have a class called table which has an overloaded/templated member function named scan_index() in order to handle strings as a special case. class table : boost::noncopyable { public: template <typename T> void scan_index(T val, std::function<bool (uint recno, T val)> callback) { // code } void scan_index(std::string val, std::function<bool (uint recno, std::string val)> callback) { // code } }; Then there is a hitlist class which has a number of templated member functions which call table::scan_index(T, ...) class hitlist { public: template <typename T> void eq(uint fieldno, T value) { table* index_table = db.get_index_table(fieldno); // code index_table->scan_index<T>(value, [&](uint recno, T n)->bool { // code }); } }; And, finally, the code which kicks it all off: hitlist hl; // code hl.eq<std::string>(*fieldno, p1.to_string()); The problem is that instead of calling table::scan_index(std::string, ...), it calls the templated version. I have tried using both overloading (as shown above) and a specialized function template (below), but nothing seems to work. After staring at this code for a few hours, I feel like I'm missing something obvious. Any ideas? template <> void scan_index<std::string>(std::string val, std::function<bool (uint recno, std::string val)> callback) { // code }

    Read the article

  • C++/boost generator module, feedback/critic please

    - by aaa
    hello. I wrote this generator, and I think to submit to boost people. Can you give me some feedback about it it basically allows to collapse multidimensional loops to flat multi-index queue. Loop can be boost lambda expressions. Main reason for doing this is to make parallel loops easier and separate algorithm from controlling structure (my fieldwork is computational chemistry where deep loops are common) 1 #ifndef _GENERATOR_HPP_ 2 #define _GENERATOR_HPP_ 3 4 #include <boost/array.hpp> 5 #include <boost/lambda/lambda.hpp> 6 #include <boost/noncopyable.hpp> 7 8 #include <boost/mpl/bool.hpp> 9 #include <boost/mpl/int.hpp> 10 #include <boost/mpl/for_each.hpp> 11 #include <boost/mpl/range_c.hpp> 12 #include <boost/mpl/vector.hpp> 13 #include <boost/mpl/transform.hpp> 14 #include <boost/mpl/erase.hpp> 15 16 #include <boost/fusion/include/vector.hpp> 17 #include <boost/fusion/include/for_each.hpp> 18 #include <boost/fusion/include/at_c.hpp> 19 #include <boost/fusion/mpl.hpp> 20 #include <boost/fusion/include/as_vector.hpp> 21 22 #include <memory> 23 24 /** 25 for loop generator which can use lambda expressions. 26 27 For example: 28 @code 29 using namespace generator; 30 using namespace boost::lambda; 31 make_for(N, N, range(bind(std::max<int>, _1, _2), N), range(_2, _3+1)); 32 // equivalent to pseudocode 33 // for l=0,N: for k=0,N: for j=max(l,k),N: for i=k,j 34 @endcode 35 36 If range is given as upper bound only, 37 lower bound is assumed to be default constructed 38 Lambda placeholders may only reference first three indices. 39 */ 40 41 namespace generator { 42 namespace detail { 43 44 using boost::lambda::constant_type; 45 using boost::lambda::constant; 46 47 /// lambda expression identity 48 template<class E, class enable = void> 49 struct lambda { 50 typedef E type; 51 }; 52 53 /// transform/construct constant lambda expression from non-lambda 54 template<class E> 55 struct lambda<E, typename boost::disable_if< 56 boost::lambda::is_lambda_functor<E> >::type> 57 { 58 struct constant : boost::lambda::constant_type<E>::type { 59 typedef typename boost::lambda::constant_type<E>::type base_type; 60 constant() : base_type(boost::lambda::constant(E())) {} 61 constant(const E &e) : base_type(boost::lambda::constant(e)) {} 62 }; 63 typedef constant type; 64 }; 65 66 /// range functor 67 template<class L, class U> 68 struct range_ { 69 typedef boost::array<int,4> index_type; 70 range_(U upper) : bounds_(typename lambda<L>::type(), upper) {} 71 range_(L lower, U upper) : bounds_(lower, upper) {} 72 73 template< typename T, size_t N> 74 T lower(const boost::array<T,N> &index) { 75 return bound<0>(index); 76 } 77 78 template< typename T, size_t N> 79 T upper(const boost::array<T,N> &index) { 80 return bound<1>(index); 81 } 82 83 private: 84 template<bool b, typename T> 85 T bound(const boost::array<T,1> &index) { 86 return (boost::fusion::at_c<b>(bounds_))(index[0]); 87 } 88 89 template<bool b, typename T> 90 T bound(const boost::array<T,2> &index) { 91 return (boost::fusion::at_c<b>(bounds_))(index[0], index[1]); 92 } 93 94 template<bool b, typename T, size_t N> 95 T bound(const boost::array<T,N> &index) { 96 using boost::fusion::at_c; 97 return (at_c<b>(bounds_))(index[0], index[1], index[2]); 98 } 99 100 boost::fusion::vector<typename lambda<L>::type, 101 typename lambda<U>::type> bounds_; 102 }; 103 104 template<typename T, size_t N> 105 struct for_base { 106 typedef boost::array<T,N> value_type; 107 virtual ~for_base() {} 108 virtual value_type next() = 0; 109 }; 110 111 /// N-index generator 112 template<typename T, size_t N, class R, class I> 113 struct for_ : for_base<T,N> { 114 typedef typename for_base<T,N>::value_type value_type; 115 typedef R range_tuple; 116 for_(const range_tuple &r) : r_(r), state_(true) { 117 boost::fusion::for_each(r_, initialize(index)); 118 } 119 /// @return new generator 120 for_* new_() { return new for_(r_); } 121 /// @return next index value and increment 122 value_type next() { 123 value_type next; 124 using namespace boost::lambda; 125 typename value_type::iterator n = next.begin(); 126 typename value_type::iterator i = index.begin(); 127 boost::mpl::for_each<I>(*(var(n))++ = var(i)[_1]); 128 129 state_ = advance<N>(r_, index); 130 return next; 131 } 132 /// @return false if out of bounds, true otherwise 133 operator bool() { return state_; } 134 135 private: 136 /// initialize indices 137 struct initialize { 138 value_type &index_; 139 mutable size_t i_; 140 initialize(value_type &index) : index_(index), i_(0) {} 141 template<class R_> void operator()(R_& r) const { 142 index_[i_++] = r.lower(index_); 143 } 144 }; 145 146 /// advance index[0:M) 147 template<size_t M> 148 struct advance { 149 /// stop recursion 150 struct stop { 151 stop(R r, value_type &index) {} 152 }; 153 /// advance index 154 /// @param r range tuple 155 /// @param index index array 156 advance(R &r, value_type &index) : index_(index), i_(0) { 157 namespace fusion = boost::fusion; 158 index[M-1] += 1; // increment index 159 fusion::for_each(r, *this); // update indices 160 state_ = index[M-1] >= fusion::at_c<M-1>(r).upper(index); 161 if (state_) { // out of bounds 162 typename boost::mpl::if_c<(M > 1), 163 advance<M-1>, stop>::type(r, index); 164 } 165 } 166 /// apply lower bound of range to index 167 template<typename R_> void operator()(R_& r) const { 168 if (i_ >= M) index_[i_] = r.lower(index_); 169 ++i_; 170 } 171 /// @return false if out of bounds, true otherwise 172 operator bool() { return state_; } 173 private: 174 value_type &index_; ///< index array reference 175 mutable size_t i_; ///< running index 176 bool state_; ///< out of bounds state 177 }; 178 179 value_type index; 180 range_tuple r_; 181 bool state_; 182 }; 183 184 185 /// polymorphic generator template base 186 template<typename T,size_t N> 187 struct For : boost::noncopyable { 188 typedef boost::array<T,N> value_type; 189 /// @return next index value and increment 190 value_type next() { return for_->next(); } 191 /// @return false if out of bounds, true otherwise 192 operator bool() const { return for_; } 193 protected: 194 /// reset smart pointer 195 void reset(for_base<T,N> *f) { for_.reset(f); } 196 std::auto_ptr<for_base<T,N> > for_; 197 }; 198 199 /// range [T,R) type 200 template<typename T, typename R> 201 struct range_type { 202 typedef range_<T,R> type; 203 }; 204 205 /// range identity specialization 206 template<typename T, class L, class U> 207 struct range_type<T, range_<L,U> > { 208 typedef range_<L,U> type; 209 }; 210 211 namespace fusion = boost::fusion; 212 namespace mpl = boost::mpl; 213 214 template<typename T, size_t N, class R1, class R2, class R3, class R4> 215 struct range_tuple { 216 // full range vector 217 typedef typename mpl::vector<R1,R2,R3,R4> v; 218 typedef typename mpl::end<v>::type end; 219 typedef typename mpl::advance_c<typename mpl::begin<v>::type, N>::type pos; 220 // [0:N) range vector 221 typedef typename mpl::erase<v, pos, end>::type t; 222 // transform into proper range fusion::vector 223 typedef typename fusion::result_of::as_vector< 224 typename mpl::transform<t,range_type<T, mpl::_1> >::type 225 >::type type; 226 }; 227 228 229 template<typename T, size_t N, 230 class R1, class R2, class R3, class R4, 231 class O> 232 struct for_type { 233 typedef typename range_tuple<T,N,R1,R2,R3,R4>::type range_tuple; 234 typedef for_<T, N, range_tuple, O> type; 235 }; 236 237 } // namespace detail 238 239 240 /// default index order, [0:N) 241 template<size_t N> 242 struct order { 243 typedef boost::mpl::range_c<size_t,0, N> type; 244 }; 245 246 /// N-loop generator, 0 < N <= 5 247 /// @tparam T index type 248 /// @tparam N number of indices/loops 249 /// @tparam R1,... range types 250 /// @tparam O index order 251 template<typename T, size_t N, 252 class R1, class R2 = void, class R3 = void, class R4 = void, 253 class O = typename order<N>::type> 254 struct for_ : detail::for_type<T, N, R1, R2, R3, R4, O>::type { 255 typedef typename detail::for_type<T, N, R1, R2, R3, R4, O>::type base_type; 256 typedef typename base_type::range_tuple range_tuple; 257 for_(const range_tuple &range) : base_type(range) {} 258 }; 259 260 /// loop range [L:U) 261 /// @tparam L lower bound type 262 /// @tparam U upper bound type 263 /// @return range 264 template<class L, class U> 265 detail::range_<L,U> range(L lower, U upper) { 266 return detail::range_<L,U>(lower, upper); 267 } 268 269 /// make 4-loop generator with specified index ordering 270 template<typename T, class R1, class R2, class R3, class R4, class O> 271 for_<T, 4, R1, R2, R3, R4, O> 272 make_for(R1 r1, R2 r2, R3 r3, R4 r4, const O&) { 273 typedef for_<T, 4, R1, R2, R3, R4, O> F; 274 return F(F::range_tuple(r1, r2, r3, r4)); 275 } 276 277 /// polymorphic generator template forward declaration 278 template<typename T,size_t N> 279 struct For; 280 281 /// polymorphic 4-loop generator 282 template<typename T> 283 struct For<T,4> : detail::For<T,4> { 284 /// generator with default index ordering 285 template<class R1, class R2, class R3, class R4> 286 For(R1 r1, R2 r2, R3 r3, R4 r4) { 287 this->reset(make_for<T>(r1, r2, r3, r4).new_()); 288 } 289 /// generator with specified index ordering 290 template<class R1, class R2, class R3, class R4, class O> 291 For(R1 r1, R2 r2, R3 r3, R4 r4, O o) { 292 this->reset(make_for<T>(r1, r2, r3, r4, o).new_()); 293 } 294 }; 295 296 } 297 298 299 #endif /* _GENERATOR_HPP_ */

    Read the article

  • python object to native c++ pointer

    - by Lodle
    Im toying around with the idea to use python as an embedded scripting language for a project im working on and have got most things working. However i cant seem to be able to convert a python extended object back into a native c++ pointer. So this is my class: class CGEGameModeBase { public: virtual void FunctionCall()=0; virtual const char* StringReturn()=0; }; class CGEPYGameMode : public CGEGameModeBase, public boost::python::wrapper<CGEPYGameMode> { public: virtual void FunctionCall() { if (override f = this->get_override("FunctionCall")) f(); } virtual const char* StringReturn() { if (override f = this->get_override("StringReturn")) return f(); return "FAILED TO CALL"; } }; Boost wrapping: BOOST_PYTHON_MODULE(GEGameMode) { class_<CGEGameModeBase, boost::noncopyable>("CGEGameModeBase", no_init); class_<CGEPYGameMode, bases<CGEGameModeBase> >("CGEPYGameMode", no_init) .def("FunctionCall", &CGEPYGameMode::FunctionCall) .def("StringReturn", &CGEPYGameMode::StringReturn); } and the python code: import GEGameMode def Ident(): return "Alpha" def NewGamePlay(): return "NewAlpha" def NewAlpha(): import GEGameMode import GEUtil class Alpha(GEGameMode.CGEPYGameMode): def __init__(self): print "Made new Alpha!" def FunctionCall(self): GEUtil.Msg("This is function test Alpha!") def StringReturn(self): return "This is return test Alpha!" return Alpha() Now i can call the first to functions fine by doing this: const char* ident = extract< const char* >( GetLocalDict()["Ident"]() ); const char* newgameplay = extract< const char* >( GetLocalDict()["NewGamePlay"]() ); printf("Loading Script: %s\n", ident); CGEPYGameMode* m_pGameMode = extract< CGEPYGameMode* >( GetLocalDict()[newgameplay]() ); However when i try and convert the Alpha class back to its base class (last line above) i get an boost error: TypeError: No registered converter was able to extract a C++ pointer to type class CGEPYGameMode from this Python object of type Alpha I have done alot of searching on the net but cant work out how to convert the Alpha object into its base class pointer. I could leave it as an object but rather have it as a pointer so some non python aware code can use it. Any ideas?

    Read the article

  • How should I delete a child object from within a parent's slot? Possibly boost::asio specific.

    - by kaliatech
    I have written a network server class that maintains a std::set of network clients. The network clients emit a signal to the network server on disconnect (via boost::bind). When a network client disconnects, the client instance needs to be removed from the Set and eventually deleted. I would think this is a common pattern, but I am having problems that might, or might not, be specific to ASIO. I've tried to trim down to just the relevant code: /** NetworkServer.hpp **/ class NetworkServices : private boost::noncopyable { public: NetworkServices(void); ~NetworkServices(void); private: void run(); void onNetworkClientEvent(NetworkClientEvent&); private: std::set<boost::shared_ptr<const NetworkClient>> clients; }; /** NetworkClient.cpp **/ void NetworkServices::run() { running = true; boost::asio::io_service::work work(io_service); //keeps service running even if no operations // This creates just one thread for the boost::asio async network services boost::thread iot(boost::bind(&NetworkServices::run_io_service, this)); while (running) { boost::system::error_code err; try { tcp::socket* socket = new tcp::socket(io_service); acceptor->accept(*socket, err); if (!err) { NetworkClient* networkClient = new NetworkClient(io_service, boost::shared_ptr<tcp::socket>(socket)); networkClient->networkClientEventSignal.connect(boost::bind(&NetworkServices::onNetworkClientEvent, this, _1)); clients.insert(boost::shared_ptr<NetworkClient>(networkClient)); networkClient->init(); //kicks off 1st asynch_read call } } // etc... } } void NetworkServices::onNetworkClientEvent(NetworkClientEvent& evt) { switch(evt.getType()) { case NetworkClientEvent::CLIENT_ERROR : { boost::shared_ptr<const NetworkClient> clientPtr = evt.getClient().getSharedPtr(); // ------ THIS IS THE MAGIC LINE ----- // If I keep this, the io_service hangs. If I comment it out, // everything works fine (but I never delete the disconnected NetworkClient). // If actually deleted the client here I might expect problems because it is the caller // of this method via boost::signal and bind. However, The clientPtr is a shared ptr, and a // reference is being kept in the client itself while signaling, so // I would the object is not going to be deleted from the heap here. That seems to be the case. // Never-the-less, this line makes all the difference, most likely because it controls whether or not the NetworkClient ever gets deleted. clients.erase(clientPtr); //I should probably put this socket clean-up in NetworkClient destructor. Regardless by doing this, // I would expect the ASIO socket stuff to be adequately cleaned-up after this. tcp::socket& socket = clientPtr->getSocket(); try { socket.shutdown(boost::asio::socket_base::shutdown_both); socket.close(); } catch(...) { CommServerContext::error("Error while shutting down and closing socket."); } break; } default : { break; } } } /** NetworkClient.hpp **/ class NetworkClient : public boost::enable_shared_from_this<NetworkClient>, Client { NetworkClient(boost::asio::io_service& io_service, boost::shared_ptr<tcp::socket> socket); virtual ~NetworkClient(void); inline boost::shared_ptr<const NetworkClient> getSharedPtr() const { return shared_from_this(); }; boost::signal <void (NetworkClientEvent&)> networkClientEventSignal; void onAsyncReadHeader(const boost::system::error_code& error, size_t bytes_transferred); }; /** NetworkClient.cpp - onAsyncReadHeader method called from io_service.run() thread as result of an async_read operation. Error condition usually result of an unexpected client disconnect.**/ void NetworkClient::onAsyncReadHeader( const boost::system::error_code& error, size_t bytes_transferred) { if (error) { //Make sure this instance doesn't get deleted from parent/slot deferencing //Alternatively, somehow schedule for future delete? boost::shared_ptr<const NetworkClient> clientPtr = getSharedPtr(); //Signal to service that this client is disconnecting NetworkClientEvent evt(*this, NetworkClientEvent::CLIENT_ERROR); networkClientEventSignal(evt); networkClientEventSignal.disconnect_all_slots(); return; } I believe it's not safe to delete the client from within the slot handler because the function return would be ... undefined? (Interestingly, it doesn't seem to blow up on me though.) So I've used boost:shared_ptr along with shared_from_this to make sure the client doesn't get deleted until all slots have been signaled. It doesn't seem to really matter though. I believe this question is not specific to ASIO, but the problem manifests in a peculiar way when using ASIO. I have one thread executing io_service.run(). All ASIO read/write operations are performed asynchronously. Everything works fine with multiple clients connecting/disconnecting UNLESS I delete my client object from the Set per the code above. If I delete my client object, the io_service seemingly deadlocks internally and no further asynchronous operations are performed unless I start another thread. I have try/catches around the io_service.run() call and have not been able to detect any errors. Questions: Are there best practices for deleting child objects, that are also signal emitters, from within parent slots? Any ideas as to why the io_service is hanging when I delete my network client object?

    Read the article

  • How to handle failure to release a resource which is contained in a smart pointer?

    - by cj
    How should an error during resource deallocation be handled, when the object representing the resource is contained in a shared pointer? Smart pointers are a useful tool to manage resources safely. Examples of such resources are memory, disk files, database connections, or network connections. // open a connection to the local HTTP port boost::shared_ptr<Socket> socket = Socket::connect("localhost:80"); In a typical scenario, the class encapsulating the resource should be noncopyable and polymorphic. A good way to support this is to provide a factory method returning a shared pointer, and declare all constructors non-public. The shared pointers can now be copied from and assigned to freely. The object is automatically destroyed when no reference to it remains, and the destructor then releases the resource. /** A TCP/IP connection. */ class Socket { public: static boost::shared_ptr<Socket> connect(const std::string& address); virtual ~Socket(); protected: Socket(const std::string& address); private: // not implemented Socket(const Socket&); Socket& operator=(const Socket&); }; But there is a problem with this approach. The destructor must not throw, so a failure to release the resource will remain undetected. A common way out of this problem is to add a public method to release the resource. class Socket { public: virtual void close(); // may throw // ... }; Unfortunately, this approach introduces another problem: Our objects may now contain resources which have already been released. This complicates the implementation of the resource class. Even worse, it makes it possible for clients of the class to use it incorrectly. The following example may seem far-fetched, but it is a common pitfall in multi-threaded code. socket->close(); // ... size_t nread = socket->read(&buffer[0], buffer.size()); // wrong use! Either we ensure that the resource is not released before the object is destroyed, thereby losing any way to deal with a failed resource deallocation. Or we provide a way to release the resource explicitly during the object's lifetime, thereby making it possible to use the resource class incorrectly. There is a way out of this dilemma. But the solution involves using a modified shared pointer class. These modifications are likely to be controversial. Typical shared pointer implementations, such as boost::shared_ptr, require that no exception be thrown when their object's destructor is called. Generally, no destructor should ever throw, so this is a reasonable requirement. These implementations also allow a custom deleter function to be specified, which is called in lieu of the destructor when no reference to the object remains. The no-throw requirement is extended to this custom deleter function. The rationale for this requirement is clear: The shared pointer's destructor must not throw. If the deleter function does not throw, nor will the shared pointer's destructor. However, the same holds for other member functions of the shared pointer which lead to resource deallocation, e.g. reset(): If resource deallocation fails, no exception can be thrown. The solution proposed here is to allow custom deleter functions to throw. This means that the modified shared pointer's destructor must catch exceptions thrown by the deleter function. On the other hand, member functions other than the destructor, e.g. reset(), shall not catch exceptions of the deleter function (and their implementation becomes somewhat more complicated). Here is the original example, using a throwing deleter function: /** A TCP/IP connection. */ class Socket { public: static SharedPtr<Socket> connect(const std::string& address); protected: Socket(const std::string& address); virtual Socket() { } private: struct Deleter; // not implemented Socket(const Socket&); Socket& operator=(const Socket&); }; struct Socket::Deleter { void operator()(Socket* socket) { // Close the connection. If an error occurs, delete the socket // and throw an exception. delete socket; } }; SharedPtr<Socket> Socket::connect(const std::string& address) { return SharedPtr<Socket>(new Socket(address), Deleter()); } We can now use reset() to free the resource explicitly. If there is still a reference to the resource in another thread or another part of the program, calling reset() will only decrement the reference count. If this is the last reference to the resource, the resource is released. If resource deallocation fails, an exception is thrown. SharedPtr<Socket> socket = Socket::connect("localhost:80"); // ... socket.reset();

    Read the article

1