Last active
August 24, 2018 18:38
-
-
Save ahamez/7f054e77ce52fd590dad333a8da455af to your computer and use it in GitHub Desktop.
Pointer to member variable as template parameter
This file contains hidden or 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
// clang++ -std=c++17 -Wall -Wextra pointer_member.cc | |
#include <iostream> | |
struct foo | |
{ | |
int a; | |
int b; | |
}; | |
constexpr auto foo_a_ptr = &foo::a; | |
constexpr auto foo_b_ptr = &foo::b; | |
template <typename T> | |
struct bar | |
{ | |
int a; | |
int b; | |
static constexpr auto field_a = &bar::a; | |
static constexpr auto field_b = &bar::b; | |
}; | |
template <typename T> | |
constexpr auto field_a = &T::a; | |
template <typename T> | |
constexpr auto field_b = &T::b; | |
template <auto foo::* member> | |
struct increment | |
{ | |
void operator()(foo& f) const noexcept | |
{ | |
f.*member += 1; | |
} | |
}; | |
template <typename T, int T::* member> | |
struct add | |
{ | |
void operator()(T& f, int x) const noexcept | |
{ | |
f.*member += x; | |
} | |
}; | |
template <typename T, int T::* member> | |
struct sub | |
{ | |
template <typename U> | |
void operator()(bar<U>& f, int x) const noexcept | |
{ | |
f.*member -= x; | |
} | |
}; | |
template <typename T, auto T::* member> | |
void | |
decrement(T& x) | |
noexcept | |
{ | |
x.*member -= 1; | |
} | |
template <auto> | |
struct multiply; | |
template <typename T, typename U, U T::* member> | |
struct multiply<member> | |
{ | |
void operator()(T& f, U x) const noexcept | |
{ | |
f.*member *= x; | |
} | |
}; | |
template <auto member, typename T> | |
void print_field(T& a) | |
{ | |
std::cout << (a.*member); | |
} | |
// The following does not compile. | |
// template <auto member, typename T> | |
// struct multiply | |
// { | |
// void operator()(T& f, int x) const noexcept | |
// { | |
// f.*member *= x; | |
// } | |
// }; | |
int main() | |
{ | |
auto f = foo{0, 0}; | |
auto b = bar<void>{0, 0}; | |
increment<foo_a_ptr>{}(f); | |
std::cout << f.a << '\n'; | |
increment<foo_b_ptr>{}(f); | |
increment<foo_b_ptr>{}(f); | |
std::cout << f.b << '\n'; | |
increment<&foo::a>{}(f); | |
std::cout << f.a << '\n'; | |
add<foo, &foo::a>{}(f, 10); | |
std::cout << f.a << '\n'; | |
increment<field_a<foo>>{}(f); | |
std::cout << f.a << '\n'; | |
sub<bar<void>, field_a<bar<void>>>{}(b, 1); | |
std::cout << b.a << '\n'; | |
add<bar<void>, bar<void>::field_a>{}(b, 33); | |
std::cout << b.a << '\n'; | |
decrement<foo, field_a<foo>>(f); | |
std::cout << f.a << '\n'; | |
decrement<foo, field_b<foo>>(f); | |
std::cout << f.b << '\n'; | |
multiply<field_a<foo>>{}(f, 2); | |
std::cout << f.a << '\n'; | |
print_field<&foo::a>(f); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment