2013-03-01 46 views
14

Tôi muốn sử dụng một con trỏ đến một thành viên lớp như một tham số mẫu như trong:Pointer thành viên lớp như một tham số mẫu

template <class Class, class Result, Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

Sử dụng struct này như MyStruct<SomeClass, SomeResult, &SomeClass::value> variable công trình tốt, nhưng tôi không thích tôi phải chỉ định SomeClassSomeResult.

Tôi muốn sử dụng MyStruct<&SomeClass::value> variable nếu có thể, nhưng không mất khả năng vượt qua bất kỳ lớp nào và có bất kỳ loại kết quả nào.

Tôi đã thử các sau đây, nhưng cú pháp là bất hợp pháp:

template <class Class, class Result> 
template <Result Class::*Member> 
struct MyStruct { 
    // ... 
}; 

error: too many template-parameter-lists

tôi đã cố gắng sử dụng một hàm helper (mà thực sự làm việc trong Clang nhưng bị từ chối bởi GCC):

template <class Class, class Result> 
static constexpr auto makeMyStruct(Result Class::*member) -> 
MyStruct<Class, Result, member> { 
    // ... 
} 

error: use of parameter `member' outside function body
error: template argument 3 is invalid

Có thể có đơn giản MyStruct<&SomeClass::value> và nếu có thì làm cách nào?

câu hỏi liên quan mà không giải quyết câu hỏi của tôi:

+0

Đúp? http://stackoverflow.com/questions/5628121/is-it-possible-to-emulate-templateauto-x – GManNickG

+0

@GManNickG Tôi không chắc liệu câu hỏi của tôi có chứa câu hỏi khác không. Mỏ hẹp hơn nhiều, và tôi sẽ không quá hạnh phúc khi sử dụng macro. – kay

+1

Thuật ngữ này là * con trỏ tới thành viên *, không * tham chiếu * đối với thành viên. Tham chiếu và con trỏ khá khác nhau trong ngôn ngữ (tốt, không * khác * nhưng vẫn không giống nhau) –

Trả lời

2

Đây có thể là một giải pháp trong C++ 11:

bạn có thể xác định đặc điểm kiểu chung chung như sau:

template<class T> 
struct remove_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct remove_member_pointer<T Parent::*> { 
    typedef T type; 
}; 

template<class T> 
struct baseof_member_pointer { 
    typedef T type; 
}; 

template<class Parent, class T> 
struct baseof_member_pointer<T Parent::*> { 
    typedef Parent type; 
}; 

Bây giờ bạn có thể định nghĩa thêm, 4 dòng wrapper vĩ mô cho mỗi struct:

template<class Class, class Result, Result Class::*Member> 
struct _MyStruct { 
    // ... 
}; 

#define MyStruct(MemberPtr) \ 
    _MyStruct<baseof_member_pointer<decltype(MemberPtr)>::type, \ 
      remove_member_pointer<decltype(MemberPtr)>::type, \ 
      MemberPtr> 

... và sử dụng nó theo cách sau:

MyStruct(&SomeClass::value) myStruct; // <-- object of type MyStruct<&SomeClass:value> 

tôi sử dụng điều này như một giải pháp trung gian, cho đến khi chúng tôi chuyển sang C++ 17.

+0

Không phải là thứ hai '_MyStruct <' không đúng chỗ? – Quentin

+0

@Quentin: Vâng, tất nhiên, cảm ơn bạn! ;-) – ManuelAtWork

-6

Make lớp kết quả của bạn là con của mẫu lớp học của bạn. giả sử các thành viên con trỏ là một đối tượng của lớp kết quả của bạn ở nơi công cộng hoặc bất cứ điều gì, bạn có thể truy cập vào bất kỳ đối tượng bằng cách làm một cái gì đó như thế này

template <stuff for this class> :: public result 
{ 
    blah 
} 
11

Một câu trả lời cho câu hỏi của tôi đã được đề xuất trong bài báo này cho C sắp tới ++ tiêu chuẩn:

cú pháp này đã được đề xuất:

template<using typename T, T t> 
struct some_struct { /* ... */ }; 

some_struct<&A::f> x; 

Sự cần thiết cho một cấu trúc cú pháp mới cho thấy rằng bạn không thể làm điều đó ngay bây giờ.

Tôi hy vọng n3601 sẽ được chấp nhận.:-)

5

Trong C++ 17, với việc bổ sung auto trong lập luận mẫu (P0127), tôi nghĩ rằng bây giờ bạn có thể làm:

template<auto value> 
struct MyStruct {}; 

template<typename Class, typename Result, Result Class::* value> 
struct MyStruct<value> { 
    // add members using Class, Result, and value here 
    using containing_type = Class; 
}; 

typename MyStruct<&Something::theotherthing>::containing_type x = Something(); 
+0

Điều này dường như hoạt động trên clang 5.0 https://godbolt.org/g/jc3mSl –

Các vấn đề liên quan