Gặp sự cố với SFINAE. Tôi cần để có thể xác định xem một loại có một toán tử hàm thành viên-> được định nghĩa không phụ thuộc vào kiểu trả về của nó. Ví dụ sau.SFINAE - Cố gắng xác định xem loại mẫu có chức năng thành viên có kiểu trả về 'biến' không
Lớp này trong trình kiểm tra. Nó định nghĩa toán tử ->() với kiểu trả về X *. Do đó tôi sẽ không biết 'X' là gì để mã hóa nó ở mọi nơi.
template <class X>
class PointerX
{
...
X* operator->() const;
...
}
Lớp này cố gắng xác định xem thông tin T có được toán tử phương thức-> xác định hay không; bất kể những gì operator-> return type là.
template<typename T>
struct HasOperatorMemberAccessor
{
template <typename R, typename C> static R GetReturnType(R (C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, decltype(GetReturnType(&U::operator->)), &U::operator-> >*);
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
Lớp này giống hệt như trên trừ toán tử-> kiểu trả về phải là 'Đối tượng'.
template<typename T>
struct HasOperatorMemberAccessorOBJECT
{
template <typename R, typename C> static R GetReturnType(R (C::*)()const);
template<typename U, typename R, R(U::*)()const> struct SFINAE{};
template<typename U> static char Test(SFINAE<U, Object*, &U::operator-> >*); // only change is we hardcoded Object as return type.
template<typename U> static uint Test(...);
static const bool value = sizeof(Test<T>(0)) == sizeof(char);
};
Kết quả:
void main()
{
HasOperatorMemberAccessor<PointerX<Object>>::Test<PointerX<Object>>(0); // fails ::value is false; Test => Test(...)
HasOperatorMemberAccessorOBJECT<PointerX<Object>>::Test<PointerX<Object>>(0); // works! ::value is true; Test => Test(SFINAE<>*)
}
HasOperatorMemberAccessor đã không thể tìm thấy chức năng thành viên PointX của "đối tượng điều hành ->() const". Vì vậy, nó sử dụng thử nghiệm phiên bản chung của Test (...).
Tuy nhiên, HasOperatorMemberAccessorOBJECT có thể tìm thấy "Object operator ->() const" của PointX. Vì vậy, nó sử dụng Kiểm tra phiên bản thử nghiệm chuyên biệt (SFINAE *).
Cả hai nên đã có thể tìm thấy phương thức "Toán tử đối tượng ->() const"; và do đó cả hai nên sử dụng Kiểm tra phiên bản chuyên môn của Test (SFINAE *); và do đó HasOperatorMemberAccessor> :: giá trị phải đúng cho cả hai.
Sự khác biệt duy nhất giữa HasOperatorMemberAccessor và HasOperatorMemberAccessorOBJECT là HasOperatorMemberAccessorOBJECT có typename R hardcoded phản đối,
Vì vậy, vấn đề là "decltype (GetReturnType (& U :: nhà khai thác>))" không được trở về Object đúng. Tôi đã thử một số giấy phép khác nhau để khám phá kiểu trả về. Chúng như sau:
decltype(GetReturnType(&U::operator->))
typename decltype(GetReturnType(&U::operator->))
decltype(((U*)nullptr)->operator->())
typename decltype(((U*)nullptr)->operator->())
Không có tác dụng, tại sao? Tôi đang sử dụng MSVC++ 10.0.
Một điều khiến mắt bị đánh trúng là 'PointerX :: operator->' trả về 'bool *', không phải 'bool'. –
Các loại X trong PointerX không quan trọng như xa như HasOperatorMemberAccessor là có liên quan. Tôi đã cố gắng khái quát vấn đề của mình bằng cách không thêm vào nhiều đối tượng không liên quan vào ví dụ. Nếu nó quá khó hiểu, tôi sẽ thay đổi bool thành chuỗi. –
Hãy để tôi thử lại.'PointerX