2016-11-16 27 views
22

Đây là một hàm mẫu mất một con trỏ (hoặc một con trỏ như đối tượng) và một hàm thành viên:chức năng thành viên cuộc gọi trên shared_ptr thông qua con trỏ hàm thành viên trong mẫu

template <typename Ptr, typename MemberFunctor> 
int example(Ptr ptr, MemberFunctor func) 
{ 
    return (ptr->*func)(); 
} 

Nếu tác phẩm khi sử dụng với con trỏ bình thường:

struct C 
{ 
    int getId() const { return 1; } 
}; 

C* c = new C; 
example(c, &C::getId); // Works fine 

Nhưng nó không làm việc với con trỏ thông minh:

std::shared_ptr<C> c2(new C); 
example(c2, &C::getId); 

Lỗi tin nhắn:

error: C2296: '->*' : illegal, left operand has type 'std::shared_ptr<C>' 

Tại sao? và Làm thế nào để làm một cái gì đó mà làm việc với cả hai?

+1

liên quan: http://stackoverflow.com/questions/31851987/pointer-like-classes-and-the -nhà điều hành – Quentin

Trả lời

19

std::shared_ptr không hỗ trợ pointer-to-member access operator (ví dụ: ->*.*). Vì vậy, chúng tôi không thể gọi con trỏ hàm thành viên với số trực tiếp là ->*. Bạn có thể thay đổi cú pháp gọi để sử dụng operator*operator.*, hoạt động cho cả con trỏ thô và con trỏ thông minh.

template <typename Ptr, typename MemberFunctor> 
int example(Ptr ptr, MemberFunctor func) 
{ 
    return ((*ptr).*func)(); 
} 

LIVE

7

std::shared_ptr không quá tải operator ->*. Bạn có thể thêm quá tải:

template <typename Ptr, typename MemberFunctor> 
int example(std::shared_ptr<Ptr> ptr, MemberFunctor func) 
{ 
    return (ptr.get()->*func)(); 
} 
12

std::shared_ptr không có operator->*. Bạn có hai lựa chọn chính:

Bạn có thể viết một tình trạng quá tải mà phải mất một std::shared_ptr (có thể một cho std::unique_ptr cũng):

template <typename T, typename MemberFunctor> 
int example(std::shared_ptr<T> ptr, MemberFunctor func) 
{ 
    return ((ptr.get())->*func)(); 
} 

Tuy nhiên, tôi sẽ đề nghị chỉ làm example lấy một tham chiếu đến T và gọi func trên đó. example không cần phải biết gì về cách con trỏ được lưu trữ, vì vậy nó không yêu cầu tất cả các quá tải thừa này.

template <typename T, typename MemberFunctor> 
int example(T&& t, MemberFunctor func) 
{ 
    return (std::forward<T>(t).*func)(); 
} 

Bây giờ nếu bạn có một std::shared_ptr<T>, bạn muốn gọi example như:

example(*my_shared_ptr, my_func); 
Các vấn đề liên quan