Разное поведение, если тип является ссылкой - PullRequest
0 голосов
/ 05 июня 2018

Я очень часто использую функцию tryValue в своих проектах.Это простая оболочка для boost::any, которая значительно упрощает ее повседневное использование.

#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;
}

Теперь я расширил эту функцию, чтобы иметь возможность справляться со ссылками.Это дает возможность изменить значение внутри моего boost-optional на месте.

Теперь утомительно иметь в виду, если мне нужно написать tryValue или tryValueRef.Функция tryValue должна сама определять, является ли T ссылкой (или даже указателем) или нет.Функция шаблона std::is_reference<T> должна выполнять эту работу, но я не знаю, как эффективно ее использовать.

Вторая часть, которую я еще не понял, - это то, почему нужно возвращаемое значение tryValueRefдополнительные * для установки значения.

Решение

Достаточно простого переименования функции, чтобы она заработала.

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;
}
...