 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Vladimir Marko Guest
|
Posted: Sat Feb 03, 2007 12:02 am Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
On Feb 1, 8:59 am, Greg Herlihy <gre...@pacbell.net> wrote:
| Quote: | On 1/31/07 10:46 AM, in article
1170262556.334796.252...@j27g2000cwj.googlegroups.com, "Peter Dimov"
pdi...@gmail.com> wrote:
On Jan 30, 11:38 am, "Ronald Landheer-Cieslak" <blytkerc...@gmail.com
wrote:
Hello all,
I'm looking for a way to detect whether a type is complete at compile-
time (preferably a way that does not result in undefined behavior).
There is none. Any nontrivial use of is_complete violates the one
definition rule because a type X can be both complete and incomplete
in the same program, which would lead to different definitions of
is_complete<X>.
An is_complete<X> template class would not violate ODR since whether X is
complete or not, there is only one X type:
"A class type (such as łclass X˛) might be incomplete at one point in a
translation unit and complete later on; the type "class X" is the same type
at both points." [§3.9/7]
So it follows that if X is a single type then a template class like
is_complete<X> must also be just one type. ...
|
Yes, just one type. But depending on the placement of the
point of instantiation of is_complete<X> in the program,
is_complete<X>::value (that's what this traits class is meant
to provide!) is false or true. And any "nontrivial use" means
multiple points of instantiation, some where X is complete,
some where its not. ODR violation as Peter Dimov wrote.
Regards
Vladimir
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sun Feb 04, 2007 12:01 am Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
Daniel Krügler wrote:
| Quote: | Unless the standard specifically says otherwise, a
diagnostic is required, see §1.4/1:
The set of diagnosable rules consists of all syntactic
and semantic rules in this International Standard except
for those rules containing an explicit notation that no
diagnostic is required or which are described as
resulting in undefined behavior.
A diagnostic is required. And all of the compilers I have
access to (Sun CC, g++ and VC++) give it.
Thanks for that quotation, James. I must have been blinded
my the fact that I did not find any definition of "shall" in the
standard.
|
That definition comes from a meta-standard, I believe.
Something ISO defines which is common to all ISO standards.
But of course, shall simply means that you have to; it
doesn't specify the consequences of not doing so. Violating
some shall's is undefined behavior; others require a
diagnostic.
The issue is further clouded, I believe, by the fact that
the C and the C++ standard take a radically opposite
approach (although the final results are quite similar): C++
basically requires a diagnostic except where the standard
says otherwise; C only requires a diagnostic when the
standard explicitly says so.
| Quote: | Taking these rules at my hands I wonder concerning
the obviously redundant description of is_base_of traits, that a
diagnostic is required (n2157), which I quoted in my recent
contribution. So I can conclude that any explicit description
of "a diagnostic is required" is redundant and should be avoided
at best? (Honestly, essentially this explicit remark was the reason
for my wrong conclusion).
|
I'm not sure. I've not looked at the text in detail. But
the library is a bit special, since much of §17.4.3 makes
violating any of the libraries rules undefined behavior. In
particular, §17.4.3.6: "In certain cases (replacement
functions, handler functions, operations on types used to
instantiate standard library template components), the C++
Standard Library depends on components supplied by a C++
program. If these components do not meet their requirements,
the Standard places no requirements on the implementation."
(What the right hand gives, the left hand takes away:-).)
| Quote: | I further wonder concerning the conclusion often given by several
of us that "anything which's effect is not described in the standard,
causes undefined behaviour". This must be wrong than?
|
If the effect is not described in the standard, it is
undefined behavior. In the case of sizeof, it's not a
question of the effect of using it on an incomplete type not
being described; the standard says you're not allowed to use
it on an incomplete type. (I think the rule about things
not described in the standard is mostly a catch-all for any
oversights; I think the standard does try to specify
behavior for any legal program, and explicitly say what
isn't legal.)
BTW: I was most surprised in your original posting by the
statement that "Most implementations will just return 0."
Were you thinking of something else, or do you actually know
implementations where sizeof(T), where T is an incomplete
type, compiles and returns 0. (In some limited contexts,
g++, or at least older versions of g++, behaved as if
sizeof(void) was 1. But the compiler still didn't allow
explicit use of the sizeof operator in such cases.)
--
James Kanze (Gabi Software) email: james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Daniel Krügler Guest
|
Posted: Sun Feb 04, 2007 9:13 pm Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
On 4 Feb., 01:01, "James Kanze" <james.ka...@gmail.com> wrote:
| Quote: | That definition comes from a meta-standard, I believe.
Something ISO defines which is common to all ISO standards.
But of course, shall simply means that you have to; it
doesn't specify the consequences of not doing so. Violating
some shall's is undefined behavior; others require a
diagnostic.
|
OK, that is a clear position ;-)
| Quote: | The issue is further clouded, I believe, by the fact that
the C and the C++ standard take a radically opposite
approach (although the final results are quite similar): C++
basically requires a diagnostic except where the standard
says otherwise; C only requires a diagnostic when the
standard explicitly says so.
|
This is an interesting point, I wasn't aware of this subtle
difference!
| Quote: | Taking these rules at my hands I wonder concerning
the obviously redundant description of is_base_of traits, that a
diagnostic is required (n2157), which I quoted in my recent
contribution. So I can conclude that any explicit description
of "a diagnostic is required" is redundant and should be avoided
at best? (Honestly, essentially this explicit remark was the reason
for my wrong conclusion).
I'm not sure. I've not looked at the text in detail. But
the library is a bit special, since much of §17.4.3 makes
violating any of the libraries rules undefined behavior. In
particular, §17.4.3.6: "In certain cases (replacement
functions, handler functions, operations on types used to
instantiate standard library template components), the C++
Standard Library depends on components supplied by a C++
program. If these components do not meet their requirements,
the Standard places no requirements on the implementation."
|
I hope I don't put things out of context quoting the relevant sentence
here:
"Requires: If Base and Derived are class types (20.4.4.1 [Primary
classification traits]),
and are not the same type (disregarding cv-qualifiers), Derived shall
be a complete type.
A diagnostic is required if this requirement is not met."
After your explanations, I think, that this requirement concerning
diagnostics
in this situation should allow a case like this:
class Unknown;
typedef bool[std::is_base_of<Unknown, Unknown>::value];
Here we have the situation that we can deduce useful information from
a type,
which is yet incomplete (and might never be completed), which would
not lead
to an ODR violation of std::is_base_of.
| Quote: | If the effect is not described in the standard, it is
undefined behavior. In the case of sizeof, it's not a
question of the effect of using it on an incomplete type not
being described; the standard says you're not allowed to use
it on an incomplete type. (I think the rule about things
not described in the standard is mostly a catch-all for any
oversights; I think the standard does try to specify
behavior for any legal program, and explicitly say what
isn't legal.)
|
That position makes sense.
| Quote: | BTW: I was most surprised in your original posting by the
statement that "Most implementations will just return 0."
Were you thinking of something else, or do you actually know
implementations where sizeof(T), where T is an incomplete
type, compiles and returns 0. (In some limited contexts,
g++, or at least older versions of g++, behaved as if
sizeof(void) was 1. But the compiler still didn't allow
explicit use of the sizeof operator in such cases.)
|
Shhhhh, don't tell anyone! ;-)
This very conclusion was not the result from a bad compiler
experience, but from the knowledge of a typical trick to test
type completeness, namely something like:
typedef bool IncompleteTypeNotAllowed[sizeof(T)];
While such a test failure has sometimes occurred to me, I obviously
had never recognized *consciously* that the compiler diagnostic
indeed choked on the sizeof(T), not on the zero-size array type
declaration, which I expected. Oh yes, something learned again....
With Greetings from Bremen,
Daniel
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Kai-Uwe Bux Guest
|
Posted: Wed Feb 07, 2007 5:42 am Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
To mod: I tried to send this two days ago, but I did not receive
confirmation that the post arrived in the moderation queue. If this is a
doublication, please feel free to ditch this.
Peter Dimov wrote:
| Quote: | On Feb 3, 1:04 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
On the other hand, maybe we are too focused on templates. Could there be
a macro IS_COMPLETE(T) that evaluates to a compile time expression of the
desired behavior?
Even if IS_COMPLETE itself does not violate the ODR, its nontrivial
uses will, for the same reason.
|
Hm, I don't have a solution to the original problem, but I am not so sure, I
buy your argument that a macro will fail because of the ODR.
Does the following violate the ODR:
template < typename Type, unsigned long Line >
struct is_complete {
static unsigned long const line = Line;
};
#define IS_COMPLETE(Type) is_complete<Type,__LINE__>::line
#include <iostream>
int main ( void ) {
std::cout << IS_COMPLETE(int) << '\n';
std::cout << IS_COMPLETE(int) << '\n';
}
If one could realize a running counter by means of macros, one could use a
similar trick to circumvent the ODR. Unfortunately, my preprocessor skills
are virtually nonexistent, so I have no idea whether that is actually
feasible.
Best
Kai-Uwe Bux
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Ronald Landheer-Cieslak Guest
|
Posted: Sun Feb 25, 2007 2:36 am Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
On Feb 7, 12:42 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
| Quote: | Peter Dimov wrote:
On Feb 3, 1:04 am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
On the other hand, maybe we are too focused on templates. Could
there be
a macro IS_COMPLETE(T) that evaluates to a compile time
expression of the
desired behavior?
Even if IS_COMPLETE itself does not violate the ODR, its nontrivial
uses will, for the same reason.
Hm, I don't have a solution to the original problem, but I am not
so sure, I
buy your argument that a macro will fail because of the ODR.
Does the following violate the ODR:
template < typename Type, unsigned long Line
struct is_complete {
static unsigned long const line = Line;
};
#define IS_COMPLETE(Type) is_complete<Type,__LINE__>::line
#include <iostream
int main ( void ) {
std::cout << IS_COMPLETE(int) << '\n';
std::cout << IS_COMPLETE(int) << '\n';
}
No, the one-definition rule is not broken in your example, but your |
IS_COMPLETE doesn't, in any way, presume to tell us whether the given
type is complete. Imagine, though, that IS_COMPLETE would actually be
a macro that's defined as
#define IS_COMPLETE(type) _Complete(type)
in which _Complete is a compiler built-in that is convertible to a
bool (true if the given type is complete, false if not).
Though, with compiler support, this would be feasible, I agree with
Peter Dimov that any non-trivial use of such a feature would break the
one-definition rule. In any case, its use in the solution for the
Munchausen problem (https://blytkerchan.dyndns.org/~ronald/cpp/
index.php?title=The_Munchausen_Pattern) would break the ODR as two
spearate instantiations of the same traits class would have different
definitions.
Too bad, eh?
Thanks,
rlc
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Guest
|
Posted: Sat Apr 07, 2007 12:33 pm Post subject: Re: detecting, at compile-time, whether a type is complete |
|
|
I bumped to this thread while I was trying to find solution to a
problem I have with my is_complete implementation. You have pointed
out the ODR issue which the implementation has as well, but here is a
piece to the puzzle anyway:
template<typename T> struct is_complete_hlp_type {operator T();};
template<typename T> struct is_complete_hlp {static char test(const
T&); static int test(...);};
template<typename T>
struct is_complete
{
enum
{res=1==sizeof(is_complete_hlp<T>::test(is_complete_hlp_type<T>()))};
};
The problem I'm having with the implementation is that it doesn't work
with abstract types, and I believe is_abstract doesn't work with
incomplete types, so it's a chicken-egg problem. This is actually a
concrete problem in my serialization library code (support for
serializing pointers to incomplete types) thus my code fails to
compile and I was hoping if someone got an idea how to improve the
above.
Cheers, Jarkko
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ] |
|
| Back to top |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|