Last active
September 1, 2017 06:05
-
-
Save Matthewacon/ded5c64ff8d6ec99e3dc0fbf9f7778ea to your computer and use it in GitHub Desktop.
A class that **loosely enforces** both static and non-static member function implementation. See comments for more.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <iomanip> | |
#include "assert.h" | |
//Forward declare templated class | |
template<typename T> class TestingStuff; | |
//Templated superclass | |
template<typename T> | |
class TestingStuff { | |
private: | |
//Reference to templated base | |
static TestingStuff<T>* reference; | |
public: | |
//Dummy non-static member variable | |
double i = 3.1415926535897932384626433826795; | |
//public static constant static non-member function pointer | |
static constexpr void (*staticFuncRef)() = &T::doNothing; | |
//public static constant non-static sub-member function pointer | |
static constexpr void (T::*funcRef)() = &T::nonStaticDoNothing; | |
TestingStuff() { | |
/* initialize state or put public constructer into private block to enforce | |
* singleton instances, only accessible through TestingStuff<T>#getInstance | |
*/ | |
} | |
//Public static singleton fetching function | |
static TestingStuff<T>* getInstance() { | |
return reference ? ({assert(reference); reference;}) : (reference = new TestingStuff<T>()); | |
} | |
//Member function (can modify state) | |
void nonStaticDoNothing(); | |
//Static non-member friend function (can modify state) | |
friend void doNothing(); | |
}; | |
//Declare singleton TestingStuff<T>* variable so it can be assigned | |
template<typename T> TestingStuff<T>* TestingStuff<T>::reference; | |
//Struct example | |
struct TestStruct { | |
void nonStaticDoNothing() {} | |
//Static non-member function with access to member variables of 'TestStructAlias' | |
static void doNothing() { | |
std::cout << std::setprecision(53) << TestingStuff<TestStruct>::getInstance()->i << std::endl; | |
} | |
}; | |
//Simple type alias for convenience | |
typedef TestingStuff<TestStruct> TSTS; | |
//Class example | |
class SubClass : TestingStuff<SubClass> { | |
public: | |
void nonStaticDoNothing() { | |
std::cout << "Did nothing!" << std::endl; | |
} | |
static void doNothing() { | |
std::cout << "Did a static nothing!" << std::endl; | |
} | |
}; | |
//Simple type alias for convenience | |
typedef TestingStuff<SubClass> TFSC; | |
int main() { | |
//Struct inheritance | |
TestStruct ts; | |
//Considered bad practice to invoke static members like non-static members | |
ts.doNothing(); // or TestStruct::doNothing(); or TSTS::staticFuncRef(); | |
ts.nonStaticDoNothing(); // or (ts->*TSTS::funcRef)(); | |
//Class inheritance | |
SubClass* sc = new SubClass(); | |
TFSC::staticFuncRef(); // or SubClass::doNothing(); | |
(sc->*TFSC::funcRef)(); // or sc->nonStaticDoNothing(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A class that loosely enforces both static and non-static member function implementation. Why loosely? Simple: the
constexpr
statements in the public block of theTestingStuff
class cannot enforce function implementation, in the template typeT
, unless they are invoked (in which case, you'll get a compiler error if you're missing a function). To strictly enforce member implementation, simply move the function pointer assignments into the constructor of theTestingStuff
class. (Note: as a consequence of doing this, you'll also have to change the pointers over toconst
s, as they will no longer be qualifiedconstexpr
statements.)