patterncppMinor
Overloading operator ->* for smart pointers
Viewed 0 times
overloadingoperatorsmartforpointers
Problem
I am implementing a smart pointer class template and I want to overload
I ended up with the following code that seems to work quite fine. Now I have two questions:
Here is the code:
```
#include
template
struct Member_function_type_traits { };
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
class Pending_member_function_call {
typedef typename Member_function_type_traits::Object_T Object_T;
typedef typename Member_function_type_traits::Return_T Return_T;
std::pair operands;
public:
Pending_member_function_call(std::pair opr): operands{opr} { }
template
Return_T operator ()(U&&... args) {
operator -> (even if it’s rarely done). I came across Scott Meyer’s article Implementing operator -> for Smart Pointers. The article is from 1999 so I decided to try to adapt the code for C++ 14 (using parameter packs and perfect forwarding) and to improve it by adding support for pointer to data member—Meyer’s implementation only supports pointer to member functions—(which is the first of the two remaining problems of Meyer’s implementation that are listed at the section “Loose Ends” of his article and that he gives the reader as exercises to solve).I ended up with the following code that seems to work quite fine. Now I have two questions:
- Is there anything that could be improved in my code?
- How to solve the second remaining problem listed at the section “Loose Ends” of Meyer’s article? (“You can’t use user-defined pointers-to-members. If someone has overloaded operator -> to take objects that act like member pointers, you may want to support such ‘smart pointers to members’ in your smart pointer class. Unfortunately, you need traits classes to get the result type of such overloaded operator ->.”)
Here is the code:
```
#include
template
struct Member_function_type_traits { };
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
struct Member_function_type_traits {
typedef O Object_T;
typedef R Return_T;
};
template
class Pending_member_function_call {
typedef typename Member_function_type_traits::Object_T Object_T;
typedef typename Member_function_type_traits::Return_T Return_T;
std::pair operands;
public:
Pending_member_function_call(std::pair opr): operands{opr} { }
template
Return_T operator ()(U&&... args) {
Solution
Is there anything that could be improved in my code?
I think you can accomplish the same thing in much less code with just a lambda:
Could have a
How to solve the second remaining problem listed at the section “Loose Ends” of Meyer’s article?
I believe the lambda solves this problem as well.
Also you could consider
where
I think you can accomplish the same thing in much less code with just a lambda:
template
auto operator->*(U pmf) const {
return [=](auto&&... args){
return (ptr->*pmf)(std::forward(args)...);
};
}Could have a
static_assert on std::is_member_pointer for extra safety.How to solve the second remaining problem listed at the section “Loose Ends” of Meyer’s article?
I believe the lambda solves this problem as well.
Also you could consider
const propagation. If the Smart_pointer is const, do you really want to allow calling non-const member functions? I don't know. If you decide you don't, you should provde both a const and non-const overload and forward to a helper:template
auto operator->*(U pmf) {
return pending_mem_fun(ptr, pmf);
}
template
auto operator->*(U pmf) const {
return pending_mem_fun(const_cast(ptr), pmf);
}where
pending_mem_fun doesn't actually have to be a member function.Code Snippets
template <class U>
auto operator->*(U pmf) const {
return [=](auto&&... args){
return (ptr->*pmf)(std::forward<decltype(args)>(args)...);
};
}template <class U>
auto operator->*(U pmf) {
return pending_mem_fun(ptr, pmf);
}
template <class U>
auto operator->*(U pmf) const {
return pending_mem_fun(const_cast<T const*>(ptr), pmf);
}Context
StackExchange Code Review Q#116654, answer score: 7
Revisions (0)
No revisions yet.