Có thể suy ra kiểu trả về của hàm thành viên được tạo khuôn mẫu trong lớp cơ sở CRTP không?
Mặc dù việc suy ra các loại tham số hoạt động tốt nhưng nó lại thất bại với kiểu trả về. Hãy xem xét ví dụ sau.
#include
mẫu
cơ sở cấu trúc
{
mẫu
Rf(T x)
{
return static_cast(*this).f_impl(x);
}
};
cấu trúc dẫn xuất: base
{
bool f_impl(int x)
{
std::cout << "f(" << x << ")" << std::endl;
trả về đúng sự thật;
}
};
int main()
{
bool b = dẫn xuất{}.f(42);
trả về b ? 0 : 1;
}
Điều này tạo ra lỗi sau:
bool b = dẫn xuất{}.f(42);
~~~~~~~~~~^
crtp.cc:7:5: lưu ý: mẫu ứng cử viên bị bỏ qua: không thể suy ra đối số mẫu 'R'
Rf(T x)
^
1 lỗi được tạo ra.
Giả định trực quan của tôi là nếu trình biên dịch có thể f
Loại tham số được suy ra của int
, nó cũng nên áp dụng cho việc trả lại bool
, vì cả hai loại đều được biết tại thời điểm khởi tạo mẫu.
Tôi đã thử sử dụng cú pháp hàm kiểu trả về theo sau nhưng không tìm được biểu thức hợp lệ để đưa vào loại từ chối
.
编辑 1
Đối với trường hợp hàm có một hoặc nhiều đối số được tạo khuôn mẫu, Dietmar Kühl cung cấp giải pháp dựa trên việc khởi tạo mẫu lười biếng bằng cách sử dụng một lớp gián tiếp. Thật không may, điều này không có tác dụng khi hàm lớp cơ sở không có bất kỳ tham số nào, như sau:
mẫu
Rg()
{
return static_cast(*this).g_impl();
}
Cố gắng sử dụng kỹ thuật tương tự không thành công vì loại phụ thuộc không tồn tại. Làm thế nào để xử lý tình huống này?
编辑2
Như Johannes Schaub đã chỉ ra, C++11 có các tham số mẫu mặc định, vì vậy luôn có thể sử dụng g
Tùy loại nào rồi áp dụng giải pháp của Dietmar:
mẫu
auto g() -> tên kiểu g_impl_result::type
{
return static_cast(*this).g_impl();
}
Chỉnh sửa 3
Vấn đề này không còn tồn tại trong C++14 nữa, vì chúng ta đã khấu trừ kiểu trả về cho các hàm thông thường, cho phép chúng ta viết một cách đơn giản:
mẫu
cơ sở cấu trúc
{
mẫu
tự động f(T x)
{
return static_cast(*this).f_impl(x);
}
autog()
{
return static_cast(*this).g_impl();
}
};
cấu trúc dẫn xuất: base
{
bool f_impl(int x)
{
trả về đúng sự thật;
}
gấp đôi g_impl()
{
trả về 4.2;
}
};
Một lời giới thiệu bổ sung là bạn của bạn:
mẫu
cấu trúc f_impl_result
{
typedef decltype(static_cast(0)->f_impl(std::declval())) loại;
};
mẫu
cơ sở cấu trúc
{
mẫu
auto f(T x) -> tên kiểu f_impl_result::type
{
return static_cast(*this).f_impl(x);
}
};
Tôi là một lập trình viên xuất sắc, rất giỏi!