Joerg Barfurth wrote:
Hi Petr,
Petr Mladek schrieb:
On Monday 14 November 2005 10:41, Stephan Bergmann wrote:
A solution that should work is to replace uses of
getCppuType(static_cast< T * >(0));
with uses of
getCppuType<T>();
That function call is handled at template instantiation time in a way
that its correct specialization is found, for any kind of T defined in
whatever namespace. The only problem is that getCppuType<T>() has a
slightly different semantic than getCppuType(T const *), see the comment
in com/sun/star/uno/Type.h. Filed
<http://www.openoffice.org/issues/show_bug.cgi?id=57855>.
I hope I understood what you said :-)
It seems that it is not necessary to use getCppuType<T>(); The problem
is with getCppuType(T const *), in fact. I tried to define also this
function as a template in com/sun/star/uno/Type.h:
template< typename T > inline const ::com::sun::star::uno::Type &
SAL_CALL
getCppuType( const T* ) SAL_THROW( () );
This is far more invasive than the change Stephan proposed. Stephan's
idea leaves all existing function declarations untouched and only
changes the implementation of one function template (or of several -
there may be other similarly affected function templates elsewhere).
Your proposal removes dozens of existing function signatures and instead
introduces one function template. At least theoretically that change is
highly incompatible. As all functions and templates involved are inline
I am not sure how bad the practical impact is. Nevertheless that change
would have to be considered very carefully wrt. its effect on backwards
compatibility on all supported platforms.
However, note that I did not tell the whole story: :)
getCppuType<T> is currently defined in Type.hxx as calling
getCppuType(static_cast<T*>(0)), so it has exactly the same problem as
Any::operator<<=() (i.e., it does not work for a named UNO type if the
header for that type is only included after Type.hxx). My solution
would include adding explicit specializations of getCppuType<T> to all
the generated header files.
In light of that, I am not sure whether Petr's solution (of which I had
not thought yet) is not the more elegant one.
[one more inline comment down below]
Note that it was necessary to mark it as a template/specialization in
any other location, even in the .hdl, .hpp files. It was enough to add
the line:
template <>
Yes that is the crucial point. Without this the functions should be
preferred, but only the template declaration is found - and for that
declaration there is no general definition.
before each declaration/definition. The compiler was not able to link
the final library otherwise. It seems that a template specialization
or a function definition are different symbols from the compiler point
of view.
Yes they are. They could even be overloaded, so that ::getCppuType(t)
and ::getCppuType<>(t) are different calls.
Then the sources can be compiled. Even it is not necessary to use
getCppuType<T> when the function is used.
Yes, but as mentioned your change is in some ways bigger.
You talked about the problem that is described in
com/sun/star/uno/Type.h. I expect that it was this comment:
Yes.
--- cut ---
/** Gets the meta type of an IDL type.
The difference between this function template (with a type
parameter) and the overloaded getCppuType function with a single
(dummy) parameter of a specific type is that this function
template may not work for the UNO type "unsigned short"
(sal_uInt16 in C++), while the overloaded one-parameter function
may not work for the UNO type "char" (sal_Unicode in C++, which may
have the same underlying C++ type as sal_uInt16 on certain
platforms).
@return type of the given IDL type
@since UDK 3.2.0 */
template< typename T > inline const ::com::sun::star::uno::Type &
SAL_CALL
getCppuType() SAL_THROW(());
--- cut ---
I expect that it means that sal_Unicode is represented with the same
type as sal_uInt16 on some platforms, so the symbols are the same.
Yes. They are the same C++-types, at least on some platforms.
And they are different on some platforms, so we need two
implementations.
That isn't the reason. The problem is that in the language-neutral UNO
type system, the (unicode) character type is different from any integer
type. As binary UNO demand a UTF-16 representation of characters, you
really need three distinct 16-bit types:
<unicode character>
<signed short integer>
<unsigned short integer>
But on most platforms C and C++ only have two distinct 16-bit integral
types - sal_Int16 and sal_uInt16. Thus you have to choose one of them to
*also* represent sal_Unicode and for various reasons the unsigned one is
the best choice here.
But then, when you encounter that type in a generic UNO-related context
you have to decide which interpretation to choose - does this type stand
for unsigned short or unicode character here.
Am I right or is there another problem? I still do not understand why
it works when the symbols are not derived from a template.
It is not about works vs. doesn't work. Both versions 'work'. But they
work differently, so simply substituting one for the other in a template
implementation will change behavior or an existing interface.
The (older) overloaded functions getCppuType(T const*) prefers the
sal_uInt16 interpretation, i.e. the getCppuType(sal_uInt16 const*)
overload returns the UNO type data for <unsigned short integer>. To get
the type data for <unicode character> you need to call the special
getCppuCharType() [or so; from memory] function.
But the (newer) function template has an explicit specialization to
prefer the <character> interpretation. The main reason is probably that
unsigned integer types are not fully supported in the UNO type system
(iirc you can't specify them in idl), whereas character is a first class
citizen.
Unsigned integer types are deprecated in UNO, but still generally
allowed. They are *not* allowed as type arguments of instantiated
polymorphic struct type templates; the implementation of UNO's
polymorphic struct types in the C++ language binding makes use of that
fact and uses getCppuType<T> in certain places.
-Stephan
Thus, if you change the implementation of template Any::Any<T> to use
getCppuType<T>() instead of getCppuType((T*)0), then the meaning of
sal_uInt16 val = 65; Any theAny(val);
changes. Before the change the value of theAny is the unsigned number
65, afterwards it is the character 'A'.
This could be fixed by providing an explicit specialization of
Any::Any<sal_uInt16> (or, if that is difficult for some compiler, an
overloaded Any(sal_uInt16) to preserve the old semantics.
Last thing. I improved our example to show what I spoke about. The
function f is now declared as a template. It can be compiled with
gcc-4.1 even when the specialization for NS::C is declared after the
definition of the function g.
Yes. That is the property Stephan's proposal made use of as well. But he
used an existing function template instead of replacing the existing
functions by template specializations.
Ciao, Joerg
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]