Topic: Template explicit specialization


Author: Francesco <xtrigger303@gmail.com>
Date: Fri, 28 Jan 2011 01:07:51 CST
Raw View
Hi to all,

in light of what is written in 14.7.3.6/7 of the standard (template
explicit specialization), could you please confirm (or reject) my
understanding of the following code?
My understanding is that the code is ill-formed because Foobar uses
the non specialized FirstFunc template (through SecondFunc) just
before FirstFunc is specialized for the same data type ( double ).
Other than this, is the code fine? More specifically:
- is the call chain for the int type well-formed (taking into account
the initial forward declaration and the specialization)?
- supposing that the first part of the code (up to the point marked as
(1)) resides in a header file that is included in other translation
units where different specializations are present, would this scenario
violate the one definition rule (or would it be anyway ill-formed)?

Thanks a lot in advance for any insight,
Francesco

P.S.
Sorry if the formatting is messed-up, I'm still trying to understand
how to post correctly through google...

// CODE
#include <iostream>

template< typename T >
void FirstFunc( T const & inObj );

template< typename T >
void SecondFunc( T const & inObj )
{
 FirstFunc( inObj );
}

template< typename T >
void FirstFunc( T const & )
{
 std::cout << "DEFAULT\n";
}

//---------- (1)

template< >
void FirstFunc< int >( int const & ) // (2)
{
 std::cout << "SPECIAL INT\n";
}

void Foobar() // (3)
{
 SecondFunc( 1.1 );
}

template< >
void FirstFunc< double >( double const & ) // (4)
{
 std::cout << "SPECIAL DOUBLE\n";
}

//------------------------------------------------------------
int main()
{
 SecondFunc( 1 ); // apple-gcc4.2 calls specialized int
 SecondFunc( 1.1 ); // apple-gcc4.2 calls specialized double
 Foobar(); // apple-gcc4.2 calls specialized double
}
// END CODE


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: CornedBee <wasti.redl@gmx.net>
Date: Fri, 28 Jan 2011 10:14:23 CST
Raw View
On Jan 28, 8:07 am, Francesco <xtrigger...@gmail.com> wrote:
> Hi to all,
>
> in light of what is written in 14.7.3.6/7 of the standard (template
> explicit specialization), could you please confirm (or reject) my
> understanding of the following code?
> My understanding is that the code is ill-formed because Foobar uses
> the non specialized FirstFunc template (through SecondFunc) just
> before FirstFunc is specialized for the same data type ( double ).

Correct. Of course, no diagnostic is required, so in effect the
program is just undefined.

> Other than this, is the code fine? More specifically:
> - is the call chain for the int type well-formed (taking into account
> the initial forward declaration and the specialization)?

Yes.

> - supposing that the first part of the code (up to the point marked as
> (1)) resides in a header file that is included in other translation
> units where different specializations are present, would this scenario
> violate the one definition rule (or would it be anyway ill-formed)?

If one translation unit contains a specialization that is used in
another, the code is ill-formed, NDR.
If two translation units contain specializations for the same type,
the ODR is violated. This is irrespective of whether the two
specializations are identical or not.

Generally speaking, a few rules can make the mental effort required
much smaller:
1) Don't specialize function templates. Overload the functions
instead.
2) Put declarations (and when possible, definitions) for all
specializations directly after the primary template. (Unless of course
that's impossible, which is the case when you use explicit
specialization of a class template as an extension mechanism.)

Sebastian


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Sat, 29 Jan 2011 10:00:41 CST
Raw View
Francesco wrote:

> - supposing that the first part of the code (up to the point marked as
> (1)) resides in a header file that is included in other translation
> units where different specializations are present, would this scenario
> violate the one definition rule (or would it be anyway ill-formed)?
>

This depends on what you mean by "different specializations". If you
specialize the template for the same template arguments, where the
definitions of those specializations deviate from the other specialization
definitions in this TU for those arguments by meaning or sequence of tokens
according to the ODR, then you will violate the ODR, and your program
becomes ill-formed (A well-formed program cannot violate the ODR. Conforming
to the ODR is explicitly required for a program to be well-formed). No
diagnostic is required though, because your program has undefined behavior
according to the ODR.

If you specialize the template for the same arguments, and your
specializations are all marked with "inline", and all your definitions have
the same meaning and sequence of tokens (according to the ODR), then you
won't violate the rules. All your definitions will be definitions of inline
functions. This is not the case in your code though.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Francesco <xtrigger303@gmail.com>
Date: Sat, 29 Jan 2011 10:02:06 CST
Raw View
On 28 Gen, 17:14, CornedBee <wasti.r...@gmx.net> wrote:
> On Jan 28, 8:07 am, Francesco <xtrigger...@gmail.com> wrote:
>
> > Hi to all,
>
> > in light of what is written in 14.7.3.6/7 of the standard (template
> > explicit specialization), could you please confirm (or reject) my
> > understanding of the following code?
> > My understanding is that the code is ill-formed because Foobar uses
> > the non specialized FirstFunc template (through SecondFunc) just
> > before FirstFunc is specialized for the same data type ( double ).
>
> Correct. Of course, no diagnostic is required, so in effect the
> program is just undefined.

Got it.

>
> > Other than this, is the code fine? More specifically:
> > - is the call chain for the int type well-formed (taking into account
> > the initial forward declaration and the specialization)?
>
> Yes.

Great.

[ Snip stuff ]

>
> If one translation unit contains a specialization that is used in
> another, the code is ill-formed, NDR.
> If two translation units contain specializations for the same type,
> the ODR is violated. This is irrespective of whether the two
> specializations are identical or not.

Can you please elaborate more? See below    (*1*)

>
> Generally speaking, a few rules can make the mental effort required
> much smaller:
> 1) Don't specialize function templates. Overload the functions
> instead.

Got it. But I'm using the specializations as an extension mechanism,
they're defined after the main template function that uses them. So in
case of simple overloading they're not called. But I get your point (I
think).

> 2) Put declarations (and when possible, definitions) for all
> specializations directly after the primary template. (Unless of course
> that's impossible, which is the case when you use explicit
> specialization of a class template as an extension mechanism.)

Same as above, but I got the point.

>
> Sebastian
>

First of all thanks for the reply. I would really appreciate a little
bit more on what you wrote above, marked as (*1*).
Consider please the code below (include guards are omitted to shorten
up).
I would think that if you take UnitOne and UnitTwo by themselves they
should be ok.
That is:
- UnitOne should call the specialized version for int and the default
for double.
- UnitTwo should call both specialized versions.
If I understood well what you wrote, you're saying that this program
as a whole (linked) is totally ill-formed because:
1. UnitOne calls DoSome( double ) WITHOUT having available a
specialization that is present in another unit?
2. Both units include the int specialization and so this would break
the ODR, even if they're the same?

This would break my heart    ;-)
Can you please confirm or reject the above and point me to the
relevant sections in the standard, please?

Thanks in advance,
Francesco


//------------------------------------------------------------
// Default.h
// this is meant to be specialized
template< typename T >
void DoSomeAux( T const & ) {}
// this is not meant to be specialized
template< typename T >
void DoSome( T const & inObj )
{
  DoSomeAux( inObj );
}

//------------------------------------------------------------
// SpecialInt.h
#include "Default.h"
template< >
void DoSomeAux< int >( int const & ) {}

//------------------------------------------------------------
// SpecialDouble.h
#include "Default.h"
template< >
void DoSomeAux< double >( double const & ) {}

//------------------------------------------------------------
// UnitOne.cpp
#include "SpecialInt.h"
void Some()
{
  DoSome( 1 );
  DoSome( 1.1 );
}

//------------------------------------------------------------
// UnitTwo.cpp
#include "SpecialInt.h"
#include "SpecialDouble.h"
void SomeOther()
{
  DoSome( 1 );
  DoSome( 1.1 );
}


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Francesco <xtrigger303@gmail.com>
Date: Sun, 30 Jan 2011 16:29:38 CST
Raw View
Thanks to all for the replies.
After your input I reviewed a little bit the standard and I guess
these are the relevant parts:

14.7:5
    an explicit specialization shall be defined at most once in a
program (according to 3.2)
14.7.3:5
If a template, a member template or the member of a class template is
explicitly specialized then that specialization shall be declared
before the first use of that specialization that would cause an
implicit instantiation to take place, in every translation unit in
which such a use occurs; no diagnostic is required.
14.7.3:13
An explicit specialization of a function template is inline only if it
is explicitly declared to be, and independently of whether its
function template is.

So summarizing, if I use the specializations as an "extension
mechanism" (I cannot declare them right after the main template) I
must:
- be sure that the declaration of a specialization appears BEFORE ANY
use I make of that specialization
- I must define them only once (the linker would complain about
duplicate symbols)
- If I want the specialization as inline I must explicitly define it
so
- If I use inline specializations I must not define many of them with
different implementations (the linker would not complain, but ODR
would be violated)

The last three point are actually the usual behavior with non-template
functions

Hope I'm getting it right.
Thanks a lot,
Francesco


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Bart van Ingen Schenau <bart@ingen.ddns.info>
Date: Sun, 30 Jan 2011 16:28:48 CST
Raw View
Francesco Wrote:

> I would think that if you take UnitOne and UnitTwo by themselves
> they should be ok.
> That is:
> - UnitOne should call the specialized version for int and the
> default for double.
> - UnitTwo should call both specialized versions.
> If I understood well what you wrote, you're saying that this
> program as a whole (linked) is totally ill-formed
> because:
> 1. UnitOne calls DoSome( double ) WITHOUT having available
> a specialization that is present in another unit?

That is right.

> 2. Both units include the int specialization and so this would
> break the ODR, even if they're the same?

Yes, because the specialisations are not declared inline.

>
> This would break my heart   ;-)
> Can you please confirm or reject the above and point me to
> the relevant sections in the standard, please?

I don't have a coipy of the standard available here, so I can't give you an
exact quote or a section number.
However, what yopu should remember is that a specialisation of a template
(either explicit or implicit) is a regular class or function.
The only special case is that an implicit specialisation of a function
template acts as an inline function, even if there was no such specification
on the template.

Given that a specialisation is a regular function, 1 causes an ODR
violation, because the program contains two functions with the same name and
signature, but with different implementations and not all of them inline.
2 causes an ODR violation, because the program contains two non-inline
definitions of the same function.

>
> Thanks in
> advance,
> Francesco
>
Bart v Ingen Schenau


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]