TITLE: compile-time inheritance checking (Newsgroup: comp.std.c++, 30 Mar 2000) ARINTE: "Arinté" >Could you explain what this code does a little more? ALEXANDRESCU: "Andrei Alexandrescu" >> template >> class Checker >> { >> typedef char (&no)[1]; >> typedef char (&yes)[2]; >> >> yes Test(Base*); >> no Test(...); >> >> public: >> enum { CandidateIsDerivedFromBase = >> sizeof(Test((Candidate*)0)) == sizeof(yes) }; >> }; SUTTER: Herb Sutter Cute, isn't it? First, remember that both sizeof() and enum values are evaluated at compile-time; i.e., no code is actually called, they operate on types and/or compile-time values only. Next, consider the expression "Test((Candidate*)0)". It's never actually executed; it simply names a Candidate* and "calls" Test() with it so as to invoke overload resolution, which will then choose Test(Base*) as the best match iff a Candidate* can be converted to a Base*, or Test(...) otherwise. This means that if Candidate* can be converted to Base*, the type of the expression "Test((Candidate*)0)" is yes, else the type of the expression is no. Next, consider that yes and no have different sizes, and so sizeof() can distinguish between them. In fact, the value of CandidateIsDerivedFromBase, which is also evaluated at compile time, is then set to true iff Candidate is derived from Base (publicly, unambiguously, and possibly indirectly). You don't even need to define the Test() functions because they're there for the type signatures only; they're never actually called. Using the above, you can enforce template constraints at compile time. I remember reading a longer and more general Constraints technique in an article somewhere. The reference escapes me now. ALEXANDRESCU: Which reminds me that I forgot to make the two Test functions above static. _______________________________________________ cpptips mailing list http://cpptips.hyperformix.com