Hãy xem xét một lớp int Wrapper
đơn giản với phép nhân quá tải operator*=
và operator*
. Đối với toán tử "kiểu cũ" quá tải, người ta có thể xác định operator*
theo điều khoản của operator*=
và thậm chí có cả thư viện như Boost.Operators và hiện thân của nó df.operators bởi @DanielFrey làm giảm bản mẫu cho bạn.Hướng dẫn thực hiện quá trình vận hành quá tải?
Tuy nhiên, để tính toán thời gian biên dịch bằng C++ 11 constexpr
mới, sự tiện lợi này biến mất. A constexpr operator*
không thể gọi operator*=
vì sau này sửa đổi đối số bên trái (ẩn) của nó. Hơn nữa, có no overloading on constexpr, vì vậy, hãy thêm constexpr operator*
vào kết quả hiện tại của sự thiếu mơ hồ về độ phân giải quá tải.
cách tiếp cận hiện tại của tôi là:
#include <iostream>
struct Wrap
{
int value;
Wrap& operator*=(Wrap const& rhs)
{ value *= rhs.value; return *this; }
// need to comment this function because of overloading ambiguity with the constexpr version
// friend Wrap operator*(Wrap const& lhs, Wrap const& rhs)
// { return Wrap { lhs } *= rhs; }
friend constexpr Wrap operator*(Wrap const& lhs, Wrap const& rhs)
{ return { lhs.value * rhs.value }; }
};
constexpr Wrap factorial(int n)
{
return n? factorial(n - 1) * Wrap { n } : Wrap { 1 };
}
// want to be able to statically initialize these arrays
struct Hold
{
static constexpr Wrap Int[] = { factorial(0), factorial(1), factorial(2), factorial(3) };
};
int main()
{
std::cout << Hold::Int[3].value << "\n"; // 6
auto w = Wrap { 2 };
w *= Wrap { 3 };
std::cout << w.value << "\n"; // 6
}
Live output here. vấn đề của tôi với điều này là:
- trùng lặp logic nhân trong cả hai
operator*=
vàoperator*
, thay vìoperator*
được biểu diễn dưới dạngoperator*=
- do đó, Boost.Operators không còn hoạt động để giảm soạn sẵn để viết nhiều toán tử số học khác
Câu hỏi: là này cách đề nghị C++ 11 có cả một thời gian chạy operator*=
và trộn thời gian chạy/thời gian biên dịch 01.237.? C++ 14 có thay đổi bất kỳ thứ gì ở đây không, ví dụ: giảm trùng lặp logic?
CẬP NHẬT: Câu trả lời bởi @AndyProwl được chấp nhận như là thành ngữ nhưng theo đề nghị của @DyP, trong C++ 11 một thể giảm sự trùng lặp logic tại các chi phí của một bài tập thêm phong cách và phản trực giác
// define operator*= in terms of operator*
Wrap& operator*=(Wrap const& rhs)
{ *this = *this * rhs; return *this; }
Việc sử dụng của bạn cho quá tải 'thường xuyên' là gì nếu nó có thể là 'constexpr'? IIRC 'constexpr' sẽ giáng xuống một cách duyên dáng thành _runtime execution_ trong ngữ cảnh không phải 'constexpr'. – sehe
@ bạn không thể có toán tử 'constexpr * =', và vì vậy 'toán tử constexpr *' không thể gọi hàm này, và thay vào đó cần lặp lại logic của các trường trích xuất v.v. – TemplateRex
Ah, tôi bắt đầu thấy câu hỏi thực của bạn. Đó là *** không *** về việc không có quá tải 'constexpr' (bạn không cần chúng!) Mà đúng hơn là không thể chia sẻ mã vì '* =' không thể là 'constexpr'.Điều tốt tôi đã + 1 trên niềm tin tốt :) – sehe