如何用合适的what()函数来补充boost::exception

How to supplement boost::exception with a proper what() function

本文关键字:boost exception 函数 何用 what      更新时间:2023-10-16

我很喜欢boost::exception,但是我很困扰它没有提供一个合适的what()函数。现在不要感到困惑,它确实有一个很好的boost::diagnostic_information,其中包含了我想在假设的what()函数中看到的所有信息,但由于boost::exception不继承std::exception,如果我多次继承(如教程中建议的,请参阅下面的行),我得到的what()函数是std::exception基的默认无用what(),它解释不了异常。

struct my_exception: virtual std::exception, virtual boost::exception { };

现在显然我试图覆盖what(),使其返回boost::diagnostic_information,但不知何故它只是不起作用,所以我有点困惑。这可能是因为它会循环,但我不太确定。

PS:我想实现what()正确的原因是,如果你的程序从它们死亡,默认情况下它会被很多工具显示(例如,gnu编译器会显示一个很好的致命错误,并显示what(), boost单元测试工具等)。

下面是测试代码的链接

#include <boost/exception/all.hpp>
struct my_exception: virtual std::exception, virtual boost::exception {};
struct my_exception2: virtual std::exception, virtual boost::exception {
    virtual const char* what() const throw() {
        return "WHAT";
    }
};
struct my_exception3: virtual std::exception, virtual boost::exception {
    virtual const char* what() const throw() {
        return boost::diagnostic_information(this).c_str();
    }
};
int main() {
    try {
        BOOST_THROW_EXCEPTION(my_exception());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //This is useless ___ std::exception
    }
    try {
        BOOST_THROW_EXCEPTION(my_exception());
    } catch (const boost::exception& e){
        std::cout << boost::diagnostic_information(e) << std::endl; 
        //This is what I'd like to see ___ main.cpp(39): Throw in function int main() ___ Dynamic exception type: boost::exception_detail::clone_impl ___ std::exception::what: std::exception
    }
    try {
        BOOST_THROW_EXCEPTION(my_exception2());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //Overriding what usually works ___ WHAT
    }
    try {
        BOOST_THROW_EXCEPTION(my_exception3());
    } catch (const std::exception& e){
        std::cout << e.what() << std::endl; 
        //But somehow here it does not work ___ Unknown exception.
    }
}

首先,boost::diagnostic_information接受(const)引用异常,this是指针:

    return boost::diagnostic_information(*this).c_str();
                                         ^-- here

第二,一旦你解决了这个问题,正如你正确预测的那样,当boost::diagnostic_information调用std::exception::what()时,这将导致无限递归。可以使用guard成员或类似的东西来解决这个问题:

struct my_exception3: std::exception, boost::exception {
    mutable bool in_what = false;
    virtual const char* what() const throw() {
        struct g { bool &b; ~g() { b = false; } } guard{in_what};
        return in_what ? "WHAT" : (in_what = true, boost::diagnostic_information(*this).c_str());
    }
};

最后,您使用的c_str来自一个被析构的临时string。我将把这个问题的解决方法留给练习。

冠军是…

namespace boost {
    char const * diagnostic_information_what( boost::exception const & e ) throw();
}