Skip to content

Instantly share code, notes, and snippets.

@adrian17 adrian17/STL.cpp
Last active Mar 25, 2016

Embed
What would you like to do?
Examples for "make pointers to members callable"
// based on original paper
struct X{ void method(int){} };
struct Y{ int val; };
struct Z{
void lval() & {};
void rval() && {};
void const_() const {};
};
int main(){
X x;
X* px = &x;
void (X::*p_mem)(int ) = &X::method;
p_mem(x, 1); // equivalent to (x.*p_mem)(1)
p_mem(px, 1); // equivalent to ((*px).pmem)(1)
int (Y::*p_val) = &Y::val;
Y y{42};
p_val(y) = 17; // equivalent to (y.*p_val) = 17;
p_val(&y) = 17; // same as above
void (Z::*lval)() & = &Z::lval;
void (Z::*rval)() && = &Z::rval;
void (Z::*const_)() const = &Z::const_;
Z z;
const Z cz;
lval(z); // OK
lval(&z); // OK
//lval(Z{}); // error: Z{} is not an lvalue
//rval(z); // error: z is not an rvalue
rval(Z{}); // OK
const_(cz); // OK
//lval(cz); // error: can’t call non-const member function on const object
}
// and it works with standard algorithms out of the box
#include <algorithm>
#include <iostream>
#include <memory>
#include <vector>
struct S{
S(){static int N; val = N++;}
void f(){std::cout << " " << val << "\n";}
int val;
};
int main(){
{
std::vector<S> vec(3);
std::for_each(vec.begin(), vec.end(), &S::f);
std::cout << std::count_if(vec.begin(), vec.end(), &S::val) << '\n';
}
{
S s1, s2, s3;
std::vector<S*> vec = {&s1, &s2, &s3};
std::for_each(vec.begin(), vec.end(), &S::f);
std::cout << std::count_if(vec.begin(), vec.end(), &S::val) << '\n';
}
{
std::vector<std::shared_ptr<S>> vec = { std::make_shared<S>() };
std::for_each(vec.begin(), vec.end(), &S::f);
std::cout << std::count_if(vec.begin(), vec.end(), &S::val) << '\n';
}
}
// making sure it works with concepts
template<typename F, typename T>
concept bool Callable = requires(F f, T t) {
{ f(t) }
};
template<typename F, typename T>
void call(F f, T t) requires Callable<F, T> {
f(t);
}
struct S{
void f(){}
int x;
};
void f(S s){}
int main(){
S s;
S *ps;
struct {
S operator*(){static S s; return s;}
} x;
call(f, s); // sanity check
call(&S::f, s);
call(&S::x, s);
call(&S::f, ps);
call(&S::x, ps);
call(&S::f, x);
call(&S::x, x);
}
#include <cstdio>
struct B{virtual char method(){return 'S';}};
struct D : public B{char method(){return 'D';}};
int main(){
B b; D d;
B *pb = new B; B *pd = new D;
auto ptr = &B::method;
printf("%c %c\n", (b.*ptr)(), ptr(b));
printf("%c %c\n", (d.*ptr)(), ptr(d));
printf("%c %c %c\n", ((*pb).*ptr)(), (pb->*ptr)(), ptr(pb));
printf("%c %c %c\n", ((*pd).*ptr)(), (pd->*ptr)(), ptr(pd));
auto ptr2 = &D::method;
//ptr2(b); // invalid
//ptr2(pd); // invalid
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.