Created
June 24, 2014 13:42
-
-
Save torbjoernk/e327e741b3489189f497 to your computer and use it in GitHub Desktop.
a little minimal example of custom type_traits
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
/* | |
* 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