3
\$\begingroup\$

Background

In C++ unlike other OOP languages, we do not have a Base Class from where All Classes are derived. I understand in MFC and pre STL, some Compilers did had a similar model, so lets leave it out of the discussion and focus on what the standard provides.

In C++11, auto was introduced to derive the type from rvalue just another way of type deduction of templates. This was a huge relief when one has to write long list of types with all template parameters.

Using Naked Pointers were prone to errors so Smart Pointers were introduced as a remedy for the unavoidable evil.

Use Case

I have a function which should return something that would indicate Null Object when no data was found or if it found needs to return the data. I would like to know, if C++11 has an elegant way of writing the below code, considering, the template types are painful to read.

Code

std::unique_ptr<std::tuple<tstring, int, tstring> > CCOMErrorHandler::PopError()
    {
    unique_ptr<std::tuple<tstring, int, tstring> > error = nullptr;
    if (!m_lstErrors.empty())
        {
        error = std::unique_ptr<std::tuple<tstring, int, tstring> >(new std::tuple<tstring, int, tstring>(m_lstErrors.front()));
        if (error)
            {
            m_lstErrors.pop_front();
            }
        }
    return(error);
    }

One option is to use a typedef or macro replacement, but generally am not a big FAN as that keeps polluting namespace though you may have to use to few times in your code often only once.

\$\endgroup\$
4
\$\begingroup\$

The first question is, why are you using pointers in the first place here? Allocation with new should only be used when required. Perhaps it is in this case, but I'd rethink your design. Are the errors polymorphic? If so, why? If not, why do you need to use pointers?

Many STL containers use either an error-code approach, that is, they return a std::pair<T, bool>, where the bool represents success/failure, or they deal directly with iterators, and return an iterator to end() in the case of failure. Depending on the type of m_lstErrors, this could be a possibility (although obviously this won't work for a container adapter like std::stack).

Though it is not contained in the C++ standard library at the moment (it is slated for inclusion in C++14), std::optional was basically made for this purpose. In fact, it can be written using only C++11 features (and there's a reference implementation you could use here). Boost also contains a boost::optional type, although this lacks things such as move semantics and safe (explicit) bool conversion (although other than that, it is very similar in nature). This would change the code to look like this:

std::optional<std::tuple<tstring, int, tstring>> CCOMErrorHandler::PopError()
{
    typedef std::tuple<tstring, int, tstring> tuple_type;
    std::optional<tuple_type> error;
    if(!m_lstErrors.empty()) {
        error = *m_lstErrors.front();
        m_lstError.pop_front();
    }
    return error;
}

cppreference has an API reference for std::optional.

As for the complaint about template types, you can always wrap them in another namespace to help prevent pollution:

namespace mynamespace
{
namespace detail
{
    typedef std::tuple<tstring, int, tstring> error_type;
    typedef std::optional<error_type> optional_error;
}

detail::optional_error CCOMErrorHandler::PopError()
{
    //...
}
\$\endgroup\$
  • \$\begingroup\$ +1: For introducing me to std::optional, and reminding me to use namespace. The first question is, why are you using pointers in the first place here? Just, to have a unified return irrespective of presence or absence of data.Pointers works well here. Various containers have their own error-code approach, but generally (ex. for sequences) I would have to end up returning iterators, and may not always be valid outside the context (as in my example). Unless std::optional was there in the stdlib, I don't see extra mileage in using it from what I have now. \$\endgroup\$ – Abhijit Sep 25 '13 at 16:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.