Compilation sequence - a feature or bug

  • Thread starter =?iso-8859-2?q?Seweryn_Habdank-Wojew=F3dzki?=
  • Start date
?

=?iso-8859-2?q?Seweryn_Habdank-Wojew=F3dzki?=

Hi

There is an example of the code below (mostly written by P. Bindels).
In that example is strongly highlighted that very important is the
sequence
of compiled code. In C++ could be assume that such a sequence exists.
But the question is if it is a feature or it is a bug?
Especially in the scope of that example we could observe that
templates
can be somehow separated from its specializations.

Best regards.

#include <iostream>

template <class A>
class T {
A a;
};

class is_original_version_of_template
{
public:
static bool const value;
};

bool const is_original_version_of_template::value
(sizeof(T<void *>) == sizeof(T<void *>));

template <class A>
class T<A *> {
A *a[10];
};

class is_not_original_version_of_template // specialized
{
public:
static bool const value;
};

bool const is_not_original_version_of_template::value
(sizeof(T<void *>) == is_original_version_of_template::value);

int main()
{
std::cout << "is_original_version_of_template "
<< is_original_version_of_template::value << '\n';

std::cout << "is_not_original_version_of_template "
<< is_not_original_version_of_template::value << '\n';
}
 
Z

Zeppe

Seweryn said:
Hi

There is an example of the code below (mostly written by P. Bindels).
In that example is strongly highlighted that very important is the
sequence
of compiled code. In C++ could be assume that such a sequence exists.
But the question is if it is a feature or it is a bug?
Especially in the scope of that example we could observe that
templates
can be somehow separated from its specializations.

There are definite rules for the template argument resolution. Well,
actually it's a little it complex stuff, but the common-sense rule
applies the most of the times. That is, in this situation, if you want
to use a specialisation, the definition of the specialisation has to be
visible in every place in which you instantiate the templates that
whould be specialised.
#include <iostream>

template <class A>
class T {
A a;
};

class is_original_version_of_template
{
public:
static bool const value;
};

I can't understand the meaning of this code...
bool const is_original_version_of_template::value
(sizeof(T<void *>) == sizeof(T<void *>));

This is always true...
template <class A>
class T<A *> {
A *a[10];
};

Ah, that's bad. The standard (14.3.3#2) says:
Any partial specializations (14.5.4) associated with the primary class
template are considered when a specialization based on the template
template parameter is instantiated. If a specialization is not visible
at the point of instantiation, and it would have been selected had it
been visible, the program is ill-formed; no diagnostic is required.
This applies in your case.
class is_not_original_version_of_template // specialized
{
public:
static bool const value;
};

bool const is_not_original_version_of_template::value
(sizeof(T<void *>) == is_original_version_of_template::value);

Here you are comparing a size_type with a bool (that is always true).
It makes no sense.

Regards,

Zeppe
 
?

=?iso-8859-1?q?Seweryn_Habdank-Wojew=F3dzki?=

Hi!

Thanks for the reply.
Ah, that's bad. The standard (14.3.3#2) says:
Any partial specializations (14.5.4) associated with the primary class
template are considered when a specialization based on the template
template parameter is instantiated. If a specialization is not visible
at the point of instantiation, and it would have been selected had it
been visible, the program is ill-formed; no diagnostic is required.
This applies in your case.

Yes I understand. But I am looking if something is useful in that
case. I have another example of such a code. When I am blocking one
particular specialisation by using explicit instantiation before more
general specialisation. In the code calling "T<int*, double*>::value;"
will cause compilation error.

Regards.
#include <iostream>
#include <boost/static_assert.hpp>

template <class A, class B>
class T {};

template class T<int*, double*>;

template <class A, class B>
struct T<A *, B> {
A a[10];
B * b[7];
enum { value = sizeof(A*[10]) + sizeof(B*[7]) };
};

template <typename A, typename B>
struct Func { enum { value = (sizeof(T<A,B>) == 1) }; };

int main()
{
using std::cout;
//T<int*, double*>::value;
int const b = T<int*,double>::value;
int const a = T<double*,int>::value;
int const c = Func<int*,double*>::value;
BOOST_STATIC_ASSERT (c == 1);
int const d = Func<int*,double>::value;
BOOST_STATIC_ASSERT (d != 1);
cout << b << ' ' << a << ' ' << c << ' ' << d << '\n';
return a;
}
 
Z

Zeppe

Seweryn said:
Hi!

Thanks for the reply.


Yes I understand. But I am looking if something is useful in that
case.

Sorry, I;ve quoted the wrong piece of standard. The correct one is in
14.5.4#1:
If a template is partially specialized then that partial specialization
shall be declared before the first use of that partial specialization
that would cause an implicit instantiation to take place, in every
translation unit in which such a use occurs; no diagnostic is required.

It's quite different, and it seems to allow your example. But 14.6.4.1#7
tells:
A specialization for any template may have points of instantiation in
multiple translation units. If two different points of instantiation
give a template specialization different meanings according to the one
definition rule (3.2), the program is ill-formed, no diagnostic required.

In my opinion, this means that as long as you make sure that the
particular specialisation is explicitly instantiated *before* the
definition of the general specialization in all the translation units in
which it is used, it should be fine.
I have another example of such a code. When I am blocking one
particular specialisation by using explicit instantiation before more
general specialisation. In the code calling "T<int*, double*>::value;"
will cause compilation error.

I think it's fine, according to the standard paragraphs that I cited.

Regards,

Zeppe
 
?

=?iso-8859-1?q?Seweryn_Habdank-Wojew=F3dzki?=

Hi

Sorry, I;ve quoted the wrong piece of standard. The correct one is in
14.5.4#1:
If a template is partially specialized then that partial specialization
shall be declared before the first use

The question is if e.g. instantiation is a use of template or not.

so the case when you will have:

template <typename T>
class A {};

template class A<void*>; // this is use or not.

template <typename T>
class A said:
of that partial specialization
that would cause an implicit instantiation to take place, in every
translation unit in which such a use occurs; no diagnostic is required.

Regards.
 
V

Victor Bazarov

Zeppe said:
What do you mean as "use of template"?

My guess is the OP means whatever the Standard means. The question
is, essentially, what the heck is the "use" in 14.5.4?
This one is an explicit template instantiation. It forces the template
class A to be instantiated with the paramater T = void*.

But is it a "use", in terms of the Standard?

V
 
Z

Zeppe

Seweryn said:
Hi



The question is if e.g. instantiation is a use of template or not.

What do you mean as "use of template"?
so the case when you will have:

template <typename T>
class A {};

template class A<void*>; // this is use or not.

This one is an explicit template instantiation. It forces the template
class A to be instantiated with the paramater T = void*.

Regards,

Zeppe
 
Z

Zeppe

Victor said:
My guess is the OP means whatever the Standard means. The question
is, essentially, what the heck is the "use" in 14.5.4?


But is it a "use", in terms of the Standard?
Well, I guess yes. I think that according to the standard, you can "use"
different versions (specializations) of the template. So, each time a
template must be matched, a version (the most of the time, the most
matching according to the template matching rules) will be "used".

Having said so, the standard tells in 14.5.4 that if a template is
partially specialised (that is, a partial specialisation exists in the
program) then this partial specialisation has to be declared before the
first "use" of the specialisation that would cause an implicit
instantiation to take place. Which mean that *if* there is an
instruction that "use" the specialisation (that means, that imply that
version of the template to be considered for that piece of code) *and*
this instruction _imply_ the implicit instantiation of the
specialisation (that is, a more specialised version of the general
template has not yet been explicitly, or even implicitly maybe (I have
to check), instantiated), *then* the specialisation has to come before
that instruction (obviously). And, additionally, this has to happen
consistently in the whole program.

This is IMHO.

Regards,

Zeppe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,161
Latest member
GertrudeMa
Top