godfat (owner)

Revisions

gist: 130125 Download_button fork
public
Public Clone URL: git://gist.github.com/130125.git
Embed All Files: show embed
getset.hpp #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// author:
// http://joshkos.blogspot.com/2009/06/blog-post_13.html
 
#ifndef GETSET_HPP
#define GETSET_HPP
 
template<typename T, typename C, T C::* P>
struct Selector { // used for selecting which field to access
  static T C::* const MP;
  typedef T Type;
};
 
template<typename T, typename C, T C::* P>
T C::* const Selector<T, C, P>::MP = P;
 
template<typename Derived> // Curiously Recurring Template Pattern
class GetSet { // ref. <<C++ Templates: the Complete Guide>>,
                            // <<C++ Template Metaprogramming>>
public:
  template<typename S>
  const typename S::Type& get() const {
    return static_cast<const Derived* const>(this)->*S::MP;
  }
 
  template<typename S>
  void set(const typename S::Type& value){
    static_cast<Derived* const>(this)->*S::MP = value;
  }
};
// make defining selectors easier
#define GENERATE_SELECTOR(C,T,P,N) typedef Selector< T , C , & C :: P > N
#endif
 
test.cpp #
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// godfat ~/p/t/josh> g++-mp-4.4 -std=c++98 -Wall -pedantic test.cpp -o test
// godfat ~/p/t/josh> ./test
// hack
// 0
// hack
// 2
 
#include "getset.hpp"
#include <iostream>
 
using std::cout;
using std::endl;
 
class C: public GetSet<C>{
public:
    template <typename S>
    typename S::type const& get() const;
 
// protected:
    int test;
};
 
GENERATE_SELECTOR(C, int, C::test, N);
 
template <typename S>
typename S::type const& C::get() const{
    cout << "hack" << endl;
    return GetSet<C>::get<N>();
}
 
int main(){
    C c;
 
    c.set<N>(0);
    cout << c.get<N>() << endl;
 
    c.set<N>(2);
    cout << c.get<N>() << endl;
}