このようにしないことをお勧めします。
ネストされた を使用しようとしたことをコメントで述べましたが、使用しstd::bind
ているコンパイラのバージョンに問題があります。ハッキングに頼るのではなく、メンバー クラスへの独自の繰り返しポインターをロールします。
#include <iostream>
#include <cstdint>
#include <type_traits>
#include <utility>
template<typename Ptr1, typename... Rest>
class pointer_to_sub;
template<typename ObjType, typename Class>
class pointer_to_sub<ObjType Class::* >
{
typedef ObjType Class::* ptr_type;
public:
typedef ObjType value_type;
typedef Class input_type;
pointer_to_sub(ptr_type input) : ptr(input)
{
}
value_type& operator()(input_type& from) const
{
return from.*ptr;
}
value_type const& operator()(input_type const& from) const
{
return from.*ptr;
}
value_type& operator()(input_type* from) const
{
return from->*ptr;
}
value_type const& operator()(input_type const* from) const
{
return from->*ptr;
}
private:
ptr_type ptr;
};
template<typename ObjType, typename Class, typename... Rest >
class pointer_to_sub<ObjType Class::*, Rest...> : private pointer_to_sub<Rest...>
{
typedef ObjType Class::* ptr_type;
typedef pointer_to_sub<Rest...> base_type;
public:
typedef typename base_type::value_type value_type;
typedef Class input_type;
pointer_to_sub(ptr_type input, Rest... args) : base_type(args...), ptr(input)
{
}
value_type& operator()(input_type& from) const
{
return base_type::operator()(from.*ptr);
}
value_type const& operator()(input_type const& from) const
{
return base_type::operator()(from.*ptr);
}
value_type& operator()(input_type* from) const
{
return base_type::operator()(from->*ptr);
}
value_type const& operator()(input_type const* from) const
{
return base_type::operator()(from->*ptr);
}
private:
ptr_type ptr;
};
template<typename T, typename... Args>
pointer_to_sub<T, Args...> make_pointer_to_sub(T t1, Args... args)
{
return pointer_to_sub<T, Args...>(t1, args...);
}
上記は基本的にmake_pointer_to_sub
、メンバーオブジェクトポインターのリストを取る を提供します。最初の型に変換可能な参照またはポインターを入力として受け取り、各ポインターを順番に逆参照します。unique_ptr
またはを受け入れるように改善される可能性がありますがshared_ptr
、それは後で説明します。以下のように使用します。
struct A { int x; double y;};
struct B { A a; };
int main()
{
auto ptr = make_pointer_to_sub(&B::a, &A::x);
B b = B();
ptr(b) = 1;
// b.*pointer_to(&B::a, &A::x) = 1;
std::cout << b.a.x << std::endl;
ptr(&b) = 2;
std::cout << b.a.x << std::endl;
}
必要に応じてstd::function
、適切な引数を使用してこれを に割り当てることができます。