Data Access Library (DAL)
/home/amesfoort/DAL/dal/hdf5/types/isderivedfrom.h
00001 /* Copyright 2011-2012  ASTRON, Netherlands Institute for Radio Astronomy
00002  * This file is part of the Data Access Library (DAL).
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either 
00007  * version 3 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public 
00015  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #ifndef DAL_ISDERIVEDFROM_H
00018 #define DAL_ISDERIVEDFROM_H
00019 
00020 #include "issame.h"
00021 
00022 namespace dal {
00023 
00024 // Excerpted from the book More Exceptional C++ by Herb Sutter.
00025 // see http://www.gotw.ca/publications/mxc++-item-4.htm
00026 
00048 template<typename D, typename B>
00049 class IsDerivedFrom
00050 {
00051   // 1. Create a system to allow value-checking at compile time using IsDerivedFrom<D,B>::Is
00052 
00053   class No { };
00054   class Yes { No no[3]; }; // ensure sizeof(Yes) != sizeof(No)
00055 
00056   static Yes Test( B* ); // not defined
00057   static No Test( ... ); // not defined 
00058 
00059 public:
00060   // A cast to D* steers the code to Test(B*) if B is a base class of D, and to Test(...) otherwise.
00061   // Because sizeof only evaluates types, no actual code is generated, and thus the Test() routine
00062   // implementations are not necessary.
00063   enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) }; 
00064 
00065   // 2. Force derivation if a class inherits from IsDerivedFrom.
00066 
00067   // Note that, like all template functions, the code below will only be evaluated
00068   // if it is used, allowing safe compilation of the code above.
00069 
00070 private:
00071   // Compiles only if D is-a B.
00072   static void Constraints(D* p) {
00073     B* pb = p;
00074     (void)pb; // suppress warning about an unused variable
00075   }
00076 
00077 public:
00078   IsDerivedFrom() { void(*p)(D*) = Constraints; (void)p; }
00079 };
00080 
00081 // Force it to fail in the case where B is void (unless D is void as well)
00082 
00083 template<typename D>
00084 class IsDerivedFrom<D, void>
00085 {
00086 public:
00087   enum { Is = IsSame<D, void>::Is };
00088 
00089   // Note: C++98 14.6.7 and C++11 14.6.8 say the template specialisation
00090   //       is ill-formed if it does not compile for any
00091   //       value of D. This can cause a compiler to bail
00092   //       even if this specialisation is never used.
00093   //
00094   //       clang is an example of such a compiler.
00095   IsDerivedFrom() { D* p = (void*)0; (void)p; /* error if D != void */ }
00096 };
00097 
00098 }
00099 
00100 #endif
 All Classes Functions Variables Typedefs Friends