3

私はboost::exceptionがかなり好きですが、すぐに使える適切なwhat () 関数が提供されないことにかなり悩まされています。混乱しないでください。これには、仮説関数で見たいすべての情報を含む素晴らしいboost::diagnostic_informationがありますが、多重継承した場合に取得する関数から継承されないため(チュートリアルから示唆されているように) 、以下の行を参照) は、例外について何も説明しないベースからのデフォルトの役に立たないものです。what()boost::exceptionstd::exceptionwhat()what()std::exception

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

明らかに、オーバーライドwhat()して戻そうとしましboost::diagnostic_informationたが、どういうわけかうまくいかないので、少し困惑しています。ループするためかもしれませんが、よくわかりません。

PS: 私が正しく実装したい理由what()は、多くのツールでプログラムが停止した場合にデフォルトで表示されるからです (たとえば、gnu コンパイラは致命的なエラーを表示し、what()、ブースト ユニット テスト ツールなどを表示します)。 .)。

以下のテストコードへのリンクは次のとおりです

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

2 に答える 2

3

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

最後に、c_str破壊された一時的なものから使用していますstring。その問題の解決策は演習として残しておきます。

于 2013-05-02T18:16:10.820 に答える
1

And the winner is...

namespace boost {
    char const * diagnostic_information_what( boost::exception const & e ) throw();
}
于 2013-05-03T08:54:41.497 に答える