Suppose you had a template function recursive_arrow_func(p) that
recursively applies operator-> on p, as
p.operator->().operator->().operator->() until it returns a pointer to an
object type that has no operator->
Then you could use it as:
recursive_arrow_func(p)->FuncMember();
Even if p was a pointer to pointer to pointer.
you could use this function to create one of several possible syntaxes,
using a keyword, say "arrows":
arrows(p)->FuncMember();
arrows[p]->FuncMember();
arrows{p}->FuncMember();
arrows--(p)->FuncMember();
arrows--[p]->FuncMember();
arrows(p).FuncMember();
arrows[p].FuncMember();
arrows{p}.FuncMember();
arrows--(p).FuncMember();
arrows--[p].FuncMember();
It could even do stuff like this:
template< typename T >
class my_ptr
{
private:
T* m;
public:
my_ptr(T* r) : m(r) {}
public:
T* operator->() const
{
return m;
}
T& operator*() const
{
return *m;
}
};
void g_test_recursive_arrow()
{
using element_t = std::pair< double, double >;
element_t a = { 1.5, 2.5 };
my_ptr< element_t > m = &a;
assert(a.first == arrows(m)->first);
my_ptr< my_ptr< element_t > > mm = &m;
assert(a.first == arrows(mm)->first);
my_ptr< my_ptr< my_ptr< element_t > > > mmm = &mm;
assert(a.first == arrows(mmm)->first);
element_t* p = &a;
assert(a.first == arrows(p)->first);
element_t** pp = &p;
assert(a.first == arrows(pp)->first);
element_t*** ppp = &pp;
assert(a.first == arrows(ppp)->first);
my_ptr< element_t >* pm = &m;
assert(a.first == arrows(pm)->first);
my_ptr< element_t* > mp = &p;
assert(a.first == arrows(mp)->first);
my_ptr< my_ptr< element_t >* > mpm = ±
assert(a.first == arrows(mpm)->first);
my_ptr< element_t* >* pmp = ∓
assert(a.first == arrows(pmp)->first);
}
Here's a possible implementation.
I needed a traits 'has_arrow<T>' but I couldn't find it in boost, so I
used boost::has_dereference.
So classes with operator-> must has operator* to be usable.
namespace recursive_dereferencing {
namespace detail {
template <typename T>
class has_arrow
{
public: static const bool value = boost::has_dereference<T>::value;
};
template< typename T >
class recursive_arrow_result_impl;
template< typename T, bool >
class recursive_arrow_result_impl2
{
public: using type = typename recursive_arrow_result_impl<
std::invoke_result_t< decltype(&(T::operator->)), T > >::type;
};
template< typename T >
class recursive_arrow_result_impl2< T, false >
{
public: using type = T & ;
};
template< typename T >
class recursive_arrow_result_impl
{
public: using type = typename recursive_arrow_result_impl2<T,
has_arrow<T>::value >::type;
};
template< typename T >
class recursive_arrow_result_impl<T*>
{
public: using type = typename recursive_arrow_result_impl< T >::type;
};
template< typename T >
class recursive_arrow_result_impl<T&>
{
public: using type = typename recursive_arrow_result_impl< T >::type;
};
template< typename T >
class recursive_arrow_result_impl<T*&>
{
public: using type = typename recursive_arrow_result_impl< T >::type;
};
template< typename T >
using recursive_arrow_result_impl_t = typename
recursive_arrow_result_impl<T>::type;
template< typename T >
recursive_arrow_result_impl_t<T>
recursive_arrow_impl(T&& r
, typename std::enable_if< has_arrow< T >::value >::type* = NULL
)
{
return recursive_arrow_impl(std::forward<T>(r).operator->());
}
template< typename T >
T& recursive_arrow_impl(T& r
, typename std::enable_if< !has_arrow< T >::value >::type* = NULL
)
{
return r;
}
template< typename T >
recursive_arrow_result_impl_t<T*>
recursive_arrow_impl(T* r)
{
return recursive_arrow_impl(*r);
}
template< typename T >
using recursive_arrow_result_t = std::remove_reference_t<
recursive_arrow_result_impl_t< T > >*;
template< typename T >
recursive_arrow_result_t<T> recursive_arrow(T&& r)
{
return std::addressof(recursive_arrow_impl(std::forward<T>(r)));
}
}
template< typename T >
detail::recursive_arrow_result_t<T> recursive_arrow(T&& r)
{
return detail::recursive_arrow(std::forward<T>(r));
}
}
template< typename T >
std::invoke_result_t<
decltype(&recursive_dereferencing::recursive_arrow<T>), T&& >
recursive_arrow_func(T&& r)
{
return recursive_dereferencing::recursive_arrow(std::forward<T>(r));
}
Post by t***@gmail.comHi,
If we have a container of unitque_ptr/shared_ptr objects, to reference to
*p->FuncMember();* //Same as *(*p).FuncMember();*
but, some times I need to create a pointer to this pointer and I use to
*(*p2p)->FuncMember();*
I think it will be a good idea if c++ could have a notation to this
*p2p=>FuncMember() *//or
*p2p+>FuncMember()* //or
*p2p#>FuncMember()* //or
*p2p:>FuncMember()*
What do you think?
I hope I helped in some way.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+***@isocpp.org.
To post to this group, send email to std-***@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/467a0621-ed78-4a96-b8f2-3485e059d840%40isocpp.org.