Different behaviour if type is a reference

61 Views Asked by At

I'm using the function tryValue very often in my projects. It is simple wrapper around boost::any, that simplifies greatly its everyday usage.

#include <boost/optional.hpp>
#include <boost/any.hpp>
#include <boost/optional/optional_io.hpp>
#include <iostream>

template<typename T>
boost::optional<T> tryValue(const boost::any& any) {
    try {
        boost::optional<T> ret(boost::any_cast<T>(any));
        return ret;
    }
    catch (...) {
    }
    return boost::none;
}

template<typename T>
boost::optional<T> tryValueRef(boost::any& any) {
    try {
        boost::optional<T> ret(boost::any_cast<T>(any));
        return ret;
    }
    catch (...) {
    }
    return boost::none;
}

int main(int, char**) {
    boost::any x(5);
    auto u = tryValue<int>(x);
    u = 6;
    std::cout << boost::any_cast<int>(x) << std::endl;

    auto r = tryValueRef<int&>(x);
    *r = 8; // Here I need a *? Why is that?
    std::cout << boost::any_cast<int>(x) << std::endl;
}

Now, I extended this function, so that I can deal with reference. This has the opportunity to change the value inside my boost-optional in place.

Now it is tiresome to keep in mind, if I have to write tryValue or tryValueRef. The function tryValue should figure out on its own, whether T is a reference (or even pointer) or not. The template function std::is_reference<T> should do this job, but I have no idea how to effectively use it.

A second part, that I don't understood yet, is why the return value of tryValueRef needs an extra * to set the value.

Solution

A simple renaming of the function was sufficient to make it work.

template<typename T>
boost::optional<T> tryValue(const boost::any& any) {
    try {
        boost::optional<T> ret(boost::any_cast<T>(any));
        return ret;
    }
    catch (...) {
    }
    return boost::none;
}

template<typename T>
boost::optional<T> tryValue(boost::any& any) {
    try {
        boost::optional<T> ret(boost::any_cast<T>(any));
        return ret;
    }
    catch (...) {
    }
    return boost::none;
}

int main(int, char**) {
    boost::any x(5);
    auto u = tryValue<int>(x);
    u = 6;
    std::cout << boost::any_cast<int>(x) << std::endl;

    auto v = tryValue<int&>(x);
    *v = 7;
    std::cout << boost::any_cast<int>(x) << std::endl;
}
0

There are 0 best solutions below