Skip to content

Instantly share code, notes, and snippets.

@Matthewacon
Last active September 1, 2017 06:05
Show Gist options
  • Save Matthewacon/ded5c64ff8d6ec99e3dc0fbf9f7778ea to your computer and use it in GitHub Desktop.
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.
#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();
}
@Matthewacon
Copy link
Author

A class that loosely enforces both static and non-static member function implementation. Why loosely? Simple: the constexpr statements in the public block of the TestingStuff 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 the TestingStuff class. (Note: as a consequence of doing this, you'll also have to change the pointers over to consts, as they will no longer be qualified constexpr statements.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment