Здравствуйте orangy, Вы писали:
O>фича всмысле, документированная несовместимость. O>обойти можно так:
Жалко, но все равно спасибо.
Дело в том, пробую написать обертки для объектной модели MS Word.
Хотелось бы получить такую запись для обращние к методу ОМ:
value = object.method<Policy>(parameters);
где Policy — политика обработки исключений, нулевых указателей и HRESULT, возвращаемых из Word.
Придется писать
Здравствуйте Anton V. Kolotaev, Вы писали:
AVK>Жалко, но все равно спасибо. AVK>Дело в том, пробую написать обертки для объектной модели MS Word. AVK>Хотелось бы получить такую запись для обращние к методу ОМ:
AVK>
А по-моему, так даже лучше. Тогда policy_object может быть кумулятивным, жить в промежутках между вызовами методов. Его можно настраивать... А через шаблон он всегда будет невидим за пределами метода.
Кстати, красивая идея — иметь варианты policy_object (а фактически, хэндлера ошибок).
Спасиба.
Ну, если интересно, тогда вот примерная реализация обертки
struct View
: public CComPtr<wrd::View> // можно было бы и агрегировать указатель
{
typedef CComPtr<wrd::View> base;
View () : base () {}
View (wrd::View *p)
: base (p)
{}
template <class ErrPolicy>
word::Zoom zoom (ErrPolicy & policy)
{
word::Zoom z; // z == 0if (policy.CheckPtr(p)){ // проверяем собственный указатель на 0.
// можем или обругать или промолчатьtry {
if (!policy.CheckResult(p->get_Zoom(&z))) // проверяем HRESULT
z = 0; // если произошла ошибка, z доверять нельзя
} catch (...) {
policy.OnException(); z = 0;
}
if (!z) policy.OnNullPtr();
}
return z; // можем вернуть и нулевой указатель
}
};
Если метод какой-нибудь обертки поддерживает более "продвинутый" протокол сообщений об ошибках, то можно создать политику, которая его поддерживает. В принципе можно использовать для обработки "продвинутого" протокола и стандартные политики — для этого надо определять еще четыре метода
В таком случае, "продвинутый" протокол будет вызывать Ex-методы, передавая спеифичные аргументы, которых умеют разбирать специфичные политики. В стандартных политиках выполняется действия по умолчанию.
Вот такое вот частное решение проблемы об обмене информацией между объектом и его наблюдателем.
(не совсем понял смысл двух методов работы с пойнтером).
AVK>Если метод какой-нибудь обертки поддерживает более "продвинутый" протокол сообщений об ошибках, то можно создать политику, которая его поддерживает. В принципе можно использовать для обработки "продвинутого" протокола и стандартные политики — для этого надо определять еще четыре метода
AVK>
AVK>В таком случае, "продвинутый" протокол будет вызывать Ex-методы, передавая спеифичные аргументы, которых умеют разбирать специфичные политики. В стандартных политиках выполняется действия по умолчанию.
AVK>Вот такое вот частное решение проблемы об обмене информацией между объектом и его наблюдателем.
Кстати, необязательно делать политикана шаблоном.
Можно через виртуальные функции.
Здравствуйте Кодт, Вы писали:
К>(не совсем понял смысл двух методов работы с пойнтером).
Разница в том, что CheckPtr проверяет значение указателя, по которому совершается вызов метода, а OnNullPtr содержит реакцию на возврат этим методом нулевого указателя.
Эти случаи использования очень похожи, но слегка различаются — я хотел подчеркнуть разницу, вводя два метода. В большинстве случаев они будут иметь одинаковую реализацию.
К>Кстати, необязательно делать политикана шаблоном. К>Можно через виртуальные функции.
Вот в том то и вся изюминка!
Специфичная политика может определить обработчик, который принимает больше информации.
Напрмер, можно определить разные обработчики для семейств исключений
// кстати, с троеточием я еще толком не работал, так что этот вариант может и не работать.
Для обертки, которая вызывает OnExceptionEx с параметром при использовании SpecificPolicy будут вызваны специализированные обработчики. С другой стороны, если использовать стандартную политику, то будет вызываться метод по умолчанию OnExceptionEx(...). Заметь, это несколько отличается от предлагаемого тобой варианта: у тебя обертка будет выражена в терминах интерфейса политики — чем специфичней протокол, тем более сложный будет интерфейс, и вместо специализированного обработчика нельзя будет использовать DefaultPolicy. В моем варианте такая совместимость сохранена.
Теперь продолжение реализации.
Политика должна определить как минимум четыре метода. Каждый из них может или промолчать, или выругаться, либо сделать что-нибудь еще. Чтобы упростить создание оберток, которые комбинируют разные стратегии (например, нулевой указатель и FAILED(hr) игнорируем, а на исключение ругаемся), можно использовать такой "генератор".
Здравствуйте Anton V. Kolotaev, Вы писали:
AVK>Здравствуйте Кодт, Вы писали:
К>>Кстати, необязательно делать политикана шаблоном. К>>Можно через виртуальные функции.
AVK>Вот в том то и вся изюминка!
AVK>Специфичная политика может определить обработчик, который принимает больше информации. AVK>Напрмер, можно определить разные обработчики для семейств исключений
AVK>// кстати, с троеточием я еще толком не работал, так что этот вариант может и не работать.
AVK>Для обертки, которая вызывает OnExceptionEx с параметром при использовании SpecificPolicy будут вызваны специализированные обработчики. С другой стороны, если использовать стандартную политику, то будет вызываться метод по умолчанию OnExceptionEx(...). Заметь, это несколько отличается от предлагаемого тобой варианта: у тебя обертка будет выражена в терминах интерфейса политики — чем специфичней протокол, тем более сложный будет интерфейс, и вместо специализированного обработчика нельзя будет использовать DefaultPolicy. В моем варианте такая совместимость сохранена.
К политике предъявляются требования по интерфейсу: иметь заданный набор функций с более-менее определенными сигнатурами.
Как только клиент (т.е. метод, использующий политику) потребует расширения интерфейса, то старые классы — неважно, шаблон это или класс с виртуальными методами — уже не подойдут.
В случае шаблонной реализации — чуть больше возможности для маневра: можно избегать строгой типизации аргументов — пусть компилятор плодит специализации по необходимости. Но число аргументов все равно сохранится.
(Возможно, троеточие — это выход; тогда DefaultPolicy обязан во всех своих методах держать это троеточие).
Только что проверил. VC6 работает:
class CheckNotNull
{
public:
template<class V>
bool operator() (V ptr, ...) { return ptr != NULL; }
};
class CheckExact
{
public:
template<class A, class B>
bool operator() (A value, B match, ...) { return value == match; }
};
class CheckAndRemember
{
public:
std::string diagnostics;
template<class A, class B, class D>
bool operator(A value, B match = B(), D d = 0, ...)
{
if(value == match)
return true;
diagnostics = d;
return false;
}
};
// Класс с шаблонными методами не компилится почему-то.
// Если сделать сам класс шаблонным - то все окей.
// Я сейчас ошибку искать не буду - оставлю As-Is - смысл в общем понятен.class Examinee
{
public:
template<class Check>
int Method1(Check* = 0)
{
if(Check()("hello", "hello", "dummy"))
std::cout << "passed\n";
else
std::cout << "failed\n";
}
template<class Check>
int Method2(Check& check) // допускается передача внешнего экземпляра политики
{
if(check("hello", "hello", "dummy"))
std::cout << "passed\n";
else
std::cout << "failed\n";
}
};
Examinee e;
e.Method1<CheckNotNull>();
e.Method1<CheckExact>();
CheckAndRemember cam;
e.Method2<CheckNotNull>();
e.Method2(cam);
std::cout << cam.diagnostics << endl;
AVK>Теперь продолжение реализации. AVK>Политика должна определить как минимум четыре метода. Каждый из них может или промолчать, или выругаться, либо сделать что-нибудь еще. Чтобы упростить создание оберток, которые комбинируют разные стратегии (например, нулевой указатель и FAILED(hr) игнорируем, а на исключение ругаемся), можно использовать такой "генератор".