boost::any_cast - бросать только тогда, когда неявное преобразование недоступно?

Я хочу, чтобы boost::any_cast<T> вызывал исключение только тогда, когда тип any не имеет неявного преобразования в T. Кажется, что нормальным поведением является выдача исключения, если тип any не равен T, независимо от неявных преобразований.

Пример:

boost::any a = 1;
boost::any_cast<int>(a); // This succeeds, and rightfully so
boost::any_cast<long>(a); // I don't want this to throw
boost::any_cast<Widget>(a); // I want this to throw

Может ли кто-нибудь сказать мне, есть ли простой способ получить желаемую функциональность, или, что еще лучше, дать мне вескую причину, почему существующее поведение такое, какое оно есть?


person Ben Hymers    schedule 25.11.2008    source источник


Ответы (2)


Ну, ты не можешь этого сделать. Механизм any работает следующим образом:

struct base {
    virtual ~base() { }
};

template<typename T>
struct concrete_base : base {
    T t;
    concrete_base(T t):t(t) { }
};

struct my_any {
    base * b;

    template<typename T>
    my_any(T t):b(new concrete_base<T>(t)) { }

    template<typename T>
    T any_cast() { 
        concrete_base<T> * t = dynamic_cast< concrete_base<T>* >(b);
        if(!t) throw bad_any_cast();
        return t->t;
    }
};

Надеюсь, понятно, что делает вышеизложенное. Я думаю, вы не можете делать то, что ищете. Причина в том, что здесь нет информации о сохраненном типе, которая могла бы оказаться полезной. RTTI его не предоставляет.

person Johannes Schaub - litb    schedule 25.11.2008

any_cast не может этого сделать, но если базовый и производный типы завершены (что они обычно имеют для типов, которые находятся в иерархии), вы можете реализовать свою собственную систему, которая преобразуется с помощью throw и catch, поскольку выбрасывание указателя на производный type может быть перехвачен как базовый тип указателя.

person Emil    schedule 06.06.2015
comment
throw и catch предназначены для обработки ошибок, а не для того, чтобы спотыкаться об умышленные ограничения в чужом интерфейсе. (Я не знаю достаточно, чтобы сказать, нужны ли они здесь/полезны, но я знаю, что эта идея/совет плоха в любом случае.) Если кому-то нужен контейнер для стирания типов с неявным преобразованием, то он должен написать свой собственный. - person underscore_d; 27.09.2016