【问题标题】:How to supplement boost::exception with a proper what() function如何用适当的 what() 函数补充 boost::exception
【发布时间】:2013-05-02 17:44:54
【问题描述】:

我非常喜欢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() ,增强单元测试工具等)。

Here's a link to the test code below

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

【问题讨论】:

    标签: c++ exception boost


    【解决方案1】:

    首先,boost::diagnostic_information 通过 (const) 引用获取异常,this 是一个指针:

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

    其次,一旦你解决了这个问题,正如你正确预期的那样,这会导致无限递归,因为boost::diagnostic_information 调用std::exception::what()。可以使用警卫成员或类似的东西来解决这个问题:

    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());
        }
    };
    

    最后,您正在使用来自已破坏的临时 stringc_str。我将把该问题的解决方案留作练习。

    【讨论】:

    【解决方案2】:

    获胜者是……

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

    【讨论】:

    • 如果这个答案解决了问题,你最好接受它:3。
    猜你喜欢
    • 1970-01-01
    • 2015-04-17
    • 2021-10-27
    • 2017-08-15
    • 1970-01-01
    • 2017-10-30
    • 2015-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多