1. The whole of the STLSoft exception hierarchy is
going to have a thorough going over with STLSoft 1.10. Whenever that is
...
2. I have. And discounted it. There are two
reasons.
In general, it's not a good idea to do this kind of
thing unless the different function sets have unambiguously different
signatures. For example:
Without exceptions:
Thing
*thing_ptr;
int res =
create_Thing("my thing", &thing_ptr);
With exceptions:
Thing
*thing_ptr = create_Thing("my thing");
The absence of the second (out) parameter, and
absence of an error return value, can be used to connote the throwing of
exceptions in the second case.
At first blush, it seems like we could do the same
for the COMSTL creation functions: they take an
out parameter - a reference (or pointer) to the raw/smart pointer to
receive the interface pointer.
This case
stlsoft::ref_ptr<IDispatch> disp;
HRESULT hr =
comstl::co_create_instance("Pantheios.COM.LoggerManager", disp);
clearly does not throw an exception.
We might wish to see a with-exceptions case
as:
stlsoft::ref_ptr<IDispatch> disp = comstl::co_create_instance("Pantheios.COM.LoggerManager");
The problem is, of course, that this notional
overload of co_create_instance() does not know the type of the returned smart
pointer. So, at best, we'd have to have:
stlsoft::ref_ptr<IDispatch> disp = comstl::co_create_instance<IDispatch>("Pantheios.COM.LoggerManager");
This is arguably little better, syntactically, than
the explicit case. The semantic advantage would be, of course, that it throws an
exception if the creation fails.
So that's half of one reason. The other half is
that the existing functions take a third, defaulted, parameter for the creation
context. Hence the first example shown above is equivalent to:
stlsoft::ref_ptr<IDispatch> disp;
HRESULT hr =
comstl::co_create_instance("Pantheios.COM.LoggerManager", disp,
CLSCTX_ALL);
The corresponding with-exceptions case would be
stlsoft::ref_ptr<IDispatch> disp = comstl::co_create_instance<IDispatch>("Pantheios.COM.LoggerManager",
CLSCTX_ALL);
Now there are two overloads that have two
parameters. And because these are all template functions, the compiler is lost.
Crash bang wallop to that idea.
The theoretical objection is one I've spoken of
before: the lowest level abstraction should have a single error-handling
paradigm, and because (i) such low-level features should support exception-free
components, and (ii) failure to create a COM object is not an exceptional
condition, I chose to go with HRESULTS at that level.
3. Yes. I've seen many such schemes, and Synesis
has had one for donkeys' years - called hresult - but it's just never entered
the COMSTL branch. However, since you appear to want one, I may take a look at
it again.
More fundamentally, I'm interested in considering
whether there're other approaches to, say, the co_create_instance()
issue.
I just don't have any time to devote to it at this
point, though I'm willing to chat about ideas. ;-)
Hi,
Some more questions about COMSTL:
- When and where should/would one use any and all of
the COMSTL
exceptions?
- Have you considered having exception throwing
versions of COMSTL creation (or other)
functions?
- Related to (2), has anyone got an alternative
to using if(FAILED(...))? I remember an old column in WDJ that had a MACRO
based framework for checking return values, but I was wondering if anyone
has any other approaches.
Thanks,
Adi