cuốn sách gpt4 ai đã làm

c++ - Nạp chồng hàm mẫu và triển khai SFINAE

In lại Tác giả: Taklimakan Thời gian cập nhật: 2023-11-03 00:32:54 hai mươi bốn 4
mua khóa gpt4 Nike

Tôi đang dành chút thời gian để học cách sử dụng các mẫu trong C++. Tôi chưa bao giờ sử dụng nó trước đây và không phải lúc nào tôi cũng chắc chắn những gì có thể hoặc không thể đạt được trong các tình huống khác nhau.

Như một bài tập, tôi đã gói gọn một số hàm Blas và Lapack mà tôi sử dụng trong các sự kiện của mình, hiện tại tôi đang gói ?GEL (Giải toán hệ phương trình tuyến tính).

 A x + b = 0

?GELHàm (chỉ dành cho giá trị thực) có hai tên:SGELS , đối với vectơ chính xác đơn và DGELS gấp đôi.

Ý tưởng của tôi về giao diện là một chức nănggỡ rốiVì thế:

 const std::size_t row = /* số hàng cho A */;
const std::size_t cols = /* số lượng cols cho A */;
std::array< double, row * cols > A = { /* value ​​*/ };
std::array< double, ??? > b = { /* giá trị */ }; // ???
// hàng hoặc cột Nó phụ thuộc vào người dùng.
// vấn đề, nói chung
// max( dim(x), dim(b) ) =
// tối đa( cột, hàng )
giải< double, row, cols >(A, b);
// nghiệm x được lưu trong b, do đó b
// phải đủ "lớn" để chứa x

Tùy thuộc vào yêu cầu của người dùng, các câu hỏi có thể được xác định quá mức hoặc không được xác định, có nghĩa là:

  • Nếu quyết tâm quá mứcmờ(b) > mờ(x) (Giải pháp là giả nghịch đảo)
  • nếu không chắc chắnmờ(b) < mờ(x) (Giải pháp là giảm thiểu LSQ)
  • hoặc bình thường mờ(b) = mờ(x) (Giải pháp là MỘT nghịch đảo)

(không tính đến hoàn cảnh cá nhân).

từ ?GELLưu kết quả vào vector đầu vào b , std::mảngCần có đủ không gian để chứa các giải pháp như nhận xét mã (max(hàng, cột)).

Tôi muốn xác định (tại thời điểm biên dịch) nên áp dụng giải pháp nào (đây là thay đổi tham số trong ?GELgọi). Tôi có hai hàm (tôi đơn giản hóa để giải quyết vấn đề này) xử lý độ chính xác và đã biết hàm nào là b các kích thước và hàng Số lượng/cols :

bọc không gian tên {

mẫu
void giải quyết(std::array & A, std::array & b) {
SGELS(/* Gọi đúng cách */);
}

mẫu
void giải quyết(std::array & A, std::array & b) {
DGELS(/* Được gọi đúng cách */);
}

}; /* bao bọc không gian tên */

Là một phần của lớp bọc bên trong. Hàm người dùng xác định kích thước được yêu cầu trongbThông qua vectơ mẫu:

#include 

/** Cấu trúc này tạo giá trị lớn nhất giữa các hàng và cột */
mẫu < std::size_t hàng, std::size_t cols >
cấu trúc lớn nhất_dim {
std::size_t giá trị const = std::conditional< row >= cols, std::integral_constant< std::size_t, row >,
std::integral_constant< std::size_t, cols > >::type::value;
};

/** Một kiểu cho mảng b được chọn bằng cách sử dụng "biggest_dim" */
mẫu < tên kiểu REAL_T, std::size_t hàng, std::size_t cols >
sử dụng b_array_t = std::array< REAL_T, big_dim< row, cols >::value >;

/** Ở đây chúng ta có hàm chỉ cho phép gọi với b của
* kích thước chính xác để tiếp tục */
mẫu < tên kiểu REAL_T, std::size_t hàng, std::size_t cols >
void giải quyết(std::array< REAL_T, cols * row > & A, b_array_t< REAL_T, cols, row > & b) {
static_assert(std::is_floating_point< REAL_T >::value, "Chỉ chấp nhận float/double");
quấn::giải quyết< hàng, cols, lớn nhất_dim< hàng, cols >::value >(A, b);
}

theo cách nàynó hoạt động. Nhưng tôi muốn tiến thêm một bước nữa và tôi thực sự không biết làm thế nào. Nếu người dùng cố gắng gọi gỡ rốibNếu kích thước quá nhỏ, trình biên dịch sẽ đưa ra các lỗi cực kỳ khó đọc.

Tôi đang cố gắng chèn mộttĩnh_assertĐiều này giúp người dùng hiểu được lỗi của mình. Nhưng bất kỳ hướng nào tôi nghĩ đến đều yêu cầu sử dụng hai hàm có cùng chữ ký (điều này có giống như quá tải mẫu không?) và tôi không thể tìm thấy chiến lược SFINAE (thực tế là chúng không biên dịch gì cả).

Bạn có nghĩ có thể đưa ra các xác nhận tĩnh cho các trường hợp sai không? bhiện hữuthời gian biên dịchKhông có thay đổi về giao diện người dùngKích thước? Tôi hy vọng câu hỏi này đủ rõ ràng.

@Caninonos:Đối với tôi, giao diện người dùng là cách người dùng gọi bộ giải, tức là:

 giải (ma trận A, vectơ b)

Đây là những hạn chế mà tôi đặt ra trong quá trình tập luyện để cải thiện kỹ năng của mình. Điều này có nghĩa là tôi không biết liệu giải pháp này có thực sự khả thi hay không. b Loại này phải khớp với lệnh gọi hàm, điều này có thể dễ dàng vi phạm các ràng buộc của tôi nếu tôi thêm một tham số mẫu khác và thay đổi giao diện người dùng.

Ví dụ hoàn chỉnh và hoạt động tối thiểu

Đây là một ví dụ làm việc hoàn chỉnh tối thiểu. Theo yêu cầu, tôi đã xóa mọi tham chiếu đến các khái niệm đại số tuyến tính. Đó là vấn đề về con số. Những trường hợp này là:

  • N1 = 2, N2 =2 .từ N3 = tối đa(N1, N2) = 2mọi thứ đều ổn
  • N1 = 2, N2 = 1 .từ N3 = tối đa(N1, N2) = N1 = 2mọi thứ đều ổn
  • N1 = 1, N2 =2 .từ N3 = tối đa(N1, N2) = N2 = 2mọi thứ đều ổn
  • N1 = 1, N2 =2 .từ N3 = N1 = 1 < N2Nó đã đưa ra một lỗi biên dịch chính xác. Tôi muốn chặn các lỗi biên dịch bằng một xác nhận tĩnh giải thích N3 thực tế về kích thước. là sai. Hiện tại, các lỗi rất khó đọc và khó hiểu.

您可以 xem và kiểm tra trực tuyến tại đây

câu trả lời hay nhất

Đầu tiên là một số cải tiến để đơn giản hóa thiết kế một chút và cải thiện khả năng đọc:

  • 不需要 lớn nhất_dim . tiêu chuẩn::tối đaConstexpr kể từ C++ 14. Bạn nên sử dụng cái này thay thế.

  • 不需要 b_mảng_t .bạn chỉ có thể viết std::array< REAL_T, std::max(N1, N2)>

Bây giờ để giải quyết vấn đề của bạn. Một cách tiếp cận tốt trong C++17 là:

mẫu < tên kiểu REAL_T, std::size_t N1, std::size_t N2, std::size_t N3>
void giải quyết(std::array< REAL_T, N1 * N2 > & A, std::array< REAL_T, N3> & b) {

nếu constexpr (N3 == std::max(N1, N2))
quấn::internal< N1, N2, N3 >(A, b);
khác
static_assert(N3 == std::max(N1, N2), "chiều thứ 3 không hợp lệ");

// không viết static_assert(false)
// điều này sẽ làm cho chương trình không đúng định dạng (*)
}

Hoặc, như @ max66 đã chỉ ra

mẫu < tên kiểu REAL_T, std::size_t N1, std::size_t N2, std::size_t N3>
void giải quyết(std::array< REAL_T, N1 * N2 > & A, std::array< REAL_T, N3> & b) {

static_assert(N3 == std::max(N1, N2), "chiều thứ 3 không hợp lệ");

nếu constexpr (N3 == std::max(N1, N2))
quấn::internal< N1, N2, N3 >(A, b);

}

Tadaa!! Thông báo lỗi đơn giản, thanh lịch và đẹp mắt.

constexpr nếu phiên bản có tĩnh_assert Sự khác biệt giữa:

giải quyết khoảng trống (...)
{
static_assert(...);
quấn::internal(...);
}

chỉ làtĩnh_assert? Trình biên dịch sẽ cố gắng khởi tạo bọc::nội bộngay cả trong tĩnh_assertThất bại, gây ô nhiễm đầu ra lỗi. Nếu gọi bọc::nội bộ, sau đó sử dụng constexpr khi điều kiện không thành công và không phải là một phần của phần nội dung, do đó đầu ra lỗi không có vấn đề gì.


(*) Tôi không viết static_asert(false, "thông báo lỗi) Lý do là vì điều này làm cho chương trình bị sai định dạng và không cần phải chẩn đoán. Nhìn thấy constexpr if và static_assert


Bạn cũng có thể làm float/gấp đôiNếu bạn muốn khấu trừ bằng cách di chuyển tham số mẫu sau tham số không được khấu trừ:

mẫu < std::size_t N1, std::size_t N2, std::size_t N3, tên kiểu REAL_T>
void giải quyết(std::array< REAL_T, N1 * N2 > & A, std::array< REAL_T, N3> & b) {

Vì vậy, cuộc gọi trở thành:

giải< n1_3, n2_3>(A_3, b_3);

Về c++ - nạp chồng hàm mẫu và triển khai SFINAE, chúng tôi đã tìm thấy một câu hỏi tương tự trên Stack Overflow: https://stackoverflow.com/questions/49171904/

hai mươi bốn 4 0
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress