Chciałbym utworzyć klasę, która bierze funkcję STD :: i pozwala obsłużyć określone wyjątki, ale nie jestem pewien, czy jest to możliwe.

Oto pseudo Projekt:

//exception types
template<class... Args>
class CustomExceptionHandler
{
public:
    CustomExceptionHandler(std::function<void()> clb): clb_(std::move(clb)){}

    void ExecuteCallback()
    {
        try
        {
            clb_();
        }
        /*catch specified exception types*/
    }

private:
    std::function<void()> clb_;
};

//usage
CustomExceptionHandler<std::out_of_range, std::overflow_error> handler(clb);
handler.ExecuteCallback();

Nie wiem, jak korzystać z szablonu wariatów, aby zdobyć typy wyjątków i używać go później. Czy to możliwe?

Myślę, że krotka może być pomocna.

10
Irbis 21 luty 2019, 23:47

2 odpowiedzi

Najlepsza odpowiedź

To jest możliwe! Zrobiłem rozwiązanie (które można uruchomić Tutaj), który rozszerza pakiet parametrów rodzajów wyjątków w serii wywołania funkcji rekurencyjnych, w których każda funkcja próbuje złapać jeden rodzaj wyjątku. Najlepsza rekurencyjna połączenie wywołuje wywołanie zwrotne.

namespace detail {    
    template<typename First>
    void catcher(std::function<void()>& clb){
        try {
            clb(); // invoke the callback directly
        } catch (const First& e){
            // TODO: handle error as needed
            std::cout << "Caught an exception with type \"" << typeid(e).name();
            std::cout << "\" and message \"" << e.what() << "\"\n";
        }
    }

    template<typename First, typename Second, typename... Rest>
    void catcher(std::function<void()>& clb){
        try {
            catcher<Second, Rest...>(clb); // invoke the callback inside of other handlers
        } catch (const First& e){
            // TODO: handle error as needed
            std::cout << "Caught an exception with type \"" << typeid(e).name();
            std::cout << "\" and message \"" << e.what() << "\"\n";
        }
    }
}

template<class... Args>
class CustomExceptionHandler
{
public:
    CustomExceptionHandler(std::function<void()> clb): clb_(std::move(clb)){}

    void ExecuteCallback()
    {
        detail::catcher<Args...>(clb_);
    }

private:
    std::function<void()> clb_;
};

int main(){

    std::function<void()> clb = [](){
        std::cout << "I'm gonna barf!\n";
        throw std::out_of_range("Yuck");
        //throw std::overflow_error("Ewww");
    };

    CustomExceptionHandler<std::out_of_range, std::overflow_error> handler(clb);
    handler.ExecuteCallback();

    return 0;
}

Wynik:

I'm gonna barf!

Caught an exception with type "St12out_of_range" and message "Yuck"

10
TylerH 5 marzec 2019, 15:13
template<typename E0, typename ... En>
class ExceptionCatcher
{
public:
    template<typename F>
    void doit(F&& f)
    {
        try 
        {
            ExceptionCatcher<En...> catcher;
            catcher.doit(std::forward<F>(f));
        }
        catch(const E0 &)
        {
            std::cout << __PRETTY_FUNCTION__ << '\n';
        }
    }
};

template<typename E0>
class ExceptionCatcher<E0>
{
public:
    template<typename F>
    void doit(F&& f)
    {
        try 
        {
            f();
        }
        catch(const E0 &)
        {
            std::cout << __PRETTY_FUNCTION__ << '\n';
        }
    }
};

https://wandbox.org/permlink/dauqtb9RWVMZT4B6.

2
Marek R 21 luty 2019, 21:42