Skip to content

Instantly share code, notes, and snippets.

@ahamez
Last active August 24, 2018 18:38
Show Gist options
  • Save ahamez/7f054e77ce52fd590dad333a8da455af to your computer and use it in GitHub Desktop.
Save ahamez/7f054e77ce52fd590dad333a8da455af to your computer and use it in GitHub Desktop.
Pointer to member variable as template parameter
// 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