2014-01-03 6 views
0

Моя проблема в том, что у меня есть класс шаблона, и я пытаюсь поймать исключения из разных типов данных (int, float, long, char и т. Д.).C++, Ловля исключений из разных типов данных

#include <iostream> 
using namespace std; 

const int MAX = 3; 

template<class Type> 
class Stack() 
{ 
    class Range{}; 
    class Empty{}; 
    class Input{}; 

    //Code here 
    //Code here 
    //If Error: 
    throw Range(); 
    throw Empty(); 
    throw Input(); 
} 

int main() 
{ 
    try 
    { 
     Stack<int> s1 
     Stack<float> s2 
     Stack<long> s3 
     Stack<char> s4 
    } 
    catch(Stack<int>::Range) { //Code } 
    catch(Stack<float>::Range) { //Code } 
    catch(Stack<long>::Range) { //Code } 
    catch(Stack<char>::Range) { //Code } 
    catch(Stack<int>::Empty) { //Code } 
    catch(Stack<float>::Empty) { //Code } 
    catch(Stack<long>::Empty) { //Code } 
    catch(Stack<char>::Empty) { //Code } 
    catch(Stack<int>::Input) { //Code } 
    catch(Stack<float>::Input) { //Code } 
    catch(Stack<long>::Input) { //Code } 
    catch(Stack<char>::Input) { //Code } 

return 0; 
} 

Как я могу сделать то же самое в 3 строках? Я пробовал:

template <class Type> 
catch(Stack<Type>::Range) { } 

Error: Expected 'catch' before '<' token  (What's Wrong) 


template<class Type> 
try { //Code } 
catch(Stack<Type>::Range) { } 

Error: A template declaration cannot appear at block scope (Definetely Wrong, I Know) 

template<class Type> 
int main() 
{ 
    try 
    { 
     //Code 
    } 
    catch(Stack<Type>::Range) { } 
} 

Error: Cannot declare '::main' to be a template (Of course, That's totally wrong.) 

Я попытался объявить «Type» во многих местах, хотя я знал, что это было неправильно. Если я не объявляю «Тип», это тоже неправильно. Итак, можно ли мне это сделать?

Заранее спасибо

ответ

2

Если у меня есть такая проблема (которую я хотел бы избежать в первую очередь за счет изменения вся конструкция кода) я мог бы попытаться сделать что-то вроде этого:

template<typename E> 
void TryAndCatch(
    std::function<void (void)> tried, 
    std::function<void (const E&) catched> 
) { 
    try { 
     tried(); 
    } catch (const E& exception) { 
     catched(exception); 
    } 
} 

, а затем использовать его как это:

TryAndCatch<Stack<int>::Range>(
    []() { 
     // tried code in lambda expression 
    }, 
    [](const Stack<int>::Range& exception) { 
     // catch code 
    } 
); 

Но только глядя на него бы заставил меня серьезно рассмотреть переписать кода, чтобы мне не нужно было его использовать, например. как @Spook.

Обратите внимание, что шаблон должен быть создан таким образом, чтобы вы выбрали исключение, которое вы ловите, и затем вы используете шаблоны, чтобы каким-то образом помочь вам (возможно, обернуть код в каком-либо классе шаблонов, который их обрабатывал?) Или обеспечить некоторый общий знаменатель - интерфейс, абстрактный базовый класс, ваш выбор.

+0

Ну, это слишком сложно, но это единственное решение моей проблемы ... Причина, по которой я определял исключения как подклассы, - это то, что я узнал об исключениях в этом хорошем. Спасибо –

+0

Может быть, вы должны попытаться создать некоторую оболочку/обработчик, который просто обрабатывал бы исключения? Создал ли он шаблонный класс, с типом исключения и функцией catch в качестве параметров, и просто заставил его косвенно обращаться с вашим кодом? –

+0

Ответ заслуживает +1 за «Но просто глядя на него, я настоятельно рекомендую переписать код, чтобы мне не нужно было его использовать», но это противоречие. –

3

Вообще, я не совсем уверен, если определение исключений, как подклассы является хорошей идеей. По крайней мере, я не видел этого в любой более крупной структуре (VCL, .NET, stl, но это не значит, конечно, нет).

У меня нет прямого решения вашей проблемы, но если у вас нет лучшего решения, вы всегда можете создать базовый класс для всех исключений Range и поймать их базовым классом, а не производными. Если вам нужна функциональность, специфичную для некоторого типа, вы всегда можете создать виртуальный метод в базовом классе, как:

class BaseRangeException 
{ 
public: 
    virtual void Display() = 0; 
} 

template<typename T> RangeException 
class RangeException : public BaseRangeException 
{ 
public: 
    void Display() 
    { 
     // Implement differently, depending on type of template 
    } 
} 
+0

На самом деле, это хороший и простой способ сделать это. Тем не менее, ваше решение намного лучше в этом случае, так как мне не нужно писать так много строк ... Я уверен, что разработчики C++ предсказали это и должно быть решение –

+0

Ну, это мое общее решение проблемы с дженериками - создать не общий базовый класс. Но это не решает проблему всегда. Хотя, я не уверен, что вы можете поймать исключения в общем виде. – Spook

Смежные вопросы