Skip to content

Instantly share code, notes, and snippets.

@torbjoernk
Created June 24, 2014 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save torbjoernk/e327e741b3489189f497 to your computer and use it in GitHub Desktop.
Save torbjoernk/e327e741b3489189f497 to your computer and use it in GitHub Desktop.
a little minimal example of custom type_traits
/*
* compile this with G++ or Clang++ with C++11 enabled
*
* g++ -std=c++11 -o type_traits_test type_traits_test.cpp
*
* clang++ -std=c++11 -o type_traits_test type_traits_test.cpp
*
* and pipe the output through `c++filt -t`
*
* ./type_traits_test | c++filt -t
*
* you shoud see the following
*
* BaseEncap<int, int>::traits::encap_type = BaseEncap<int, int>
* ::scalar_type = int
* ::time_type = int
* DerivedEncap<int, double>::traits::encap_type = DerivedEncap<int, double>
* ::scalar_type = int
* ::time_type = double
* SpecializedEncap<double>::traits::encap_type = SpecializedEncap<double>
* ::scalar_type = double
* ::time_type = float
* FullSpecialEncap::traits::encap_type = FullSpecialEncap
* ::scalar_type = short
* ::time_type = int
* Sweeper<BaseEncap<float, int>>::traits::sweeper_type = Sweeper<BaseEncap<float, int> >
* ::encap_type = BaseEncap<float, int>
* ::scalar_type = float
* ::time_type = int
*
*/
#include <iostream>
#include <typeinfo>
template<typename EncapT, typename ScalarT, typename TimeT>
struct encapsulation_traits {
typedef EncapT encap_type;
typedef ScalarT scalar_type;
typedef TimeT time_type;
};
template<typename ScalarT, typename TimeT>
class BaseEncap {
public:
typedef encapsulation_traits<BaseEncap<ScalarT, TimeT>, ScalarT, TimeT> traits;
virtual ~BaseEncap() {} // virtual dtor to make it polymorphic
};
// we can derive the Base as usual
template<typename ScalarT, typename TimeT>
class DerivedEncap : public BaseEncap<ScalarT, TimeT> {
public:
typedef encapsulation_traits<DerivedEncap<ScalarT, TimeT>, ScalarT, TimeT> traits;
};
// we can also use partial template specialization while deriving
template<typename ScalarT>
class SpecializedEncap : public BaseEncap<ScalarT, float> {
public:
typedef encapsulation_traits<SpecializedEncap<ScalarT>, ScalarT, float> traits;
};
// and of coarse full specialization
class FullSpecialEncap : public BaseEncap<short, int> {
public:
typedef encapsulation_traits<FullSpecialEncap, short, int> traits;
};
template<typename SweeperT, typename EncapT>
struct sweeper_traits {
typedef SweeperT sweeper_type;
// providing shortcuts to the types of EncapT
typedef typename EncapT::traits::encap_type encap_type;
typedef typename EncapT::traits::scalar_type scalar_type;
typedef typename EncapT::traits::time_type time_type;
};
template<typename EncapT>
class Sweeper {
public:
typedef sweeper_traits<Sweeper<EncapT>, EncapT> traits;
};
using namespace std;
int main(int argc, char* argv[]) {
// instantiation of an object is not necessary for the traits to work
// the objects are just here to show, that they can be instantiated
BaseEncap<int, int> b = BaseEncap<int, int>();
DerivedEncap<int, double> d = DerivedEncap<int, double>();
SpecializedEncap<double> s = SpecializedEncap<double>();
FullSpecialEncap f = FullSpecialEncap();
cout << "BaseEncap<int, int>::traits::encap_type = " << typeid(BaseEncap<int, int>::traits::encap_type).name() << endl;
cout << " ::scalar_type = " << typeid(BaseEncap<int, int>::traits::scalar_type).name() << endl;
cout << " ::time_type = " << typeid(BaseEncap<int, int>::traits::time_type).name() << endl;
cout << "DerivedEncap<int, double>::traits::encap_type = " << typeid(DerivedEncap<int, double>::traits::encap_type).name() << endl;
cout << " ::scalar_type = " << typeid(DerivedEncap<int, double>::traits::scalar_type).name() << endl;
cout << " ::time_type = " << typeid(DerivedEncap<int, double>::traits::time_type).name() << endl;
cout << "SpecializedEncap<double>::traits::encap_type = " << typeid(SpecializedEncap<double>::traits::encap_type).name() << endl;
cout << " ::scalar_type = " << typeid(SpecializedEncap<double>::traits::scalar_type).name() << endl;
cout << " ::time_type = " << typeid(SpecializedEncap<double>::traits::time_type).name() << endl;
cout << "FullSpecialEncap::traits::encap_type = " << typeid(FullSpecialEncap::traits::encap_type).name() << endl;
cout << " ::scalar_type = " << typeid(FullSpecialEncap::traits::scalar_type).name() << endl;
cout << " ::time_type = " << typeid(FullSpecialEncap::traits::time_type).name() << endl;
using sweeper = Sweeper<BaseEncap<float, int>>; // shortcut because I'm lazy
sweeper sw = sweeper(); // just to demonstrate that object instantiation works
cout << "Sweeper<BaseEncap<float, int>>::traits::sweeper_type = " << typeid(sweeper::traits::sweeper_type).name() << endl;
cout << " ::encap_type = " << typeid(sweeper::traits::encap_type).name() << endl;
cout << " ::scalar_type = " << typeid(sweeper::traits::scalar_type).name() << endl;
cout << " ::time_type = " << typeid(sweeper::traits::time_type).name() << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment