Data Access Library (DAL)
|
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