- Siêu lớp và danh mục iOS/Objective-C
- object-c - -1001 lỗi khi NSURLSession vượt qua httpproxy và /etc/hosts
- java - Nhận địa chỉ url bằng lớp mạng
- ios - Âm thanh không phát trong thông báo đẩy
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
?GEL
Hà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ối
Vì 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à:
mờ(b) > mờ(x)
(Giải pháp là giả nghịch đảo)mờ(b) < mờ(x)
(Giải pháp là giảm thiểu LSQ)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ừ ?GEL
Lưu kết quả vào vector đầu vào b
, std::mảng
Cầ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 ?GEL
gọ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 trongb
Thô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ối
Và b
Nế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? b
hiệ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.
Đâ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) = 2
mọi thứ đều ổnN1 = 2, N2 = 1
.từ N3 = tối đa(N1, N2) = N1 = 2
mọi thứ đều ổnN1 = 1, N2 =2
.từ N3 = tối đa(N1, N2) = N2 = 2
mọi thứ đều ổnN1 = 1, N2 =2
.từ N3 = N1 = 1 < N2
Nó đã đư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 đa
Constexpr 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_assert
Thấ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 đôi
Nế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/
Hàm sscanf() của ngôn ngữ C: đọc tệp tiêu đề dữ liệu theo định dạng đã chỉ định từ chuỗi: ?
Gần đây, tôi có một câu hỏi về đánh giá trước công việc mà tôi không biết cách giải quyết ngay cả khi đã truy vấn cách thức hoạt động của từng tính năng. Đây là một mã giả. Dưới đây là một hàm có tên foo() sẽ được truyền một giá trị và trả về một giá trị. Nếu bạn chuyển giá trị sau cho hàm foo,
Hàm CStr trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Chuỗi. Tham số biểu thức CStr(biểu thức) là bất kỳ biểu thức hợp lệ nào. Lưu ý rằng thông thường, bạn có thể
Hàm CSng trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Đơn. Tham số biểu thức CSng(biểu thức) là bất kỳ biểu thức hợp lệ nào. Mô tả Thông thường, nó có thể được
Hàm CreateObject tạo và trả về một tham chiếu đến đối tượng Tự động hóa. CreateObject(servername.typename [, location]) Dịch vụ tham số
Hàm Cos trả về cosin của một góc. Cos(số) Đối số số có thể là bất kỳ biểu thức số hợp lệ nào biểu thị một góc theo radian. Mô tả Hàm Cos lấy một góc và trả về tỷ lệ hai cạnh của một tam giác vuông. Tỷ lệ này là
Hàm CLng trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Dài. Tham số biểu thức CLng(biểu thức) là bất kỳ biểu thức hợp lệ nào. Mô tả Thông thường, bạn có thể sử dụng
Hàm CInt trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Số nguyên. Tham số biểu thức CInt(biểu thức) là bất kỳ biểu thức hợp lệ nào. Mô tả Thông thường, nó có thể được
Hàm Chr trả về ký tự tương ứng với mã ký tự ANSI đã chỉ định. Chr(charcode) Tham số charcode là một số xác định ký tự. Mô tả Các số từ 0 đến 31 thể hiện tiêu chuẩn không thể in được
Hàm CDbl trả về một biểu thức đã được chuyển đổi thành kiểu con Variant của Double. Tham số biểu thức CDbl(biểu thức) là bất kỳ biểu thức hợp lệ nào. Mô tả Thông thường, bạn có thể
Hàm CDate trả về một biểu thức đã được chuyển đổi thành kiểu con Biến thể của Ngày. CDate(date) Tham số ngày là bất kỳ biểu thức ngày hợp lệ nào. Giải thích rằng hàm IsDate được sử dụng để xác định d
Hàm CCur trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Tiền tệ. Tham số biểu thức CCu(biểu thức) là bất kỳ biểu thức hợp lệ nào. Mô tả Thông thường,
Hàm CByte trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Byte. Tham số biểu thức CByte(biểu thức) là bất kỳ biểu thức hợp lệ nào. Lưu ý rằng thông thường, bạn có thể
Hàm CBool trả về một biểu thức đã được chuyển đổi thành Biến thể của kiểu con Boolean. Biểu thức CBool(biểu thức) là bất kỳ biểu thức hợp lệ nào. Giải thích nếu cũ
Hàm Atn trả về arctang của một số. Tham số số Atn(number) có thể là bất kỳ biểu thức số hợp lệ nào. Mô tả: Hàm Atn tính tỷ lệ (số) hai cạnh của một tam giác vuông và trả về cung của góc tương ứng.
Hàm Asc trả về mã ký tự ANSI tương ứng với chữ cái đầu tiên của chuỗi. Asc(string) Tham số chuỗi là bất kỳ biểu thức chuỗi hợp lệ nào. Nếu tham số chuỗi không chứa ký tự thì sẽ xảy ra lỗi thời gian chạy.
Hàm Array trả về một Biến thể chứa một mảng. Array(arglist) Tham số arglist là danh sách các giá trị được phân tách bằng dấu phẩy để gán cho các phần tử mảng có trong Biến thể. Nếu tham số này không được chỉ định thì
Hàm Abs trả về giá trị tuyệt đối của một số. Abs(số) Đối số số có thể là bất kỳ biểu thức số hợp lệ nào. Nếu số chứa Null thì trả về Null; nếu biến chưa được khởi tạo thì trả về 0.
Hàm FormatPercent trả về một biểu thức đã được định dạng dưới dạng phần trăm có dấu % ở cuối (nhân với 100). FormatPercent(biểu thức[,NumDigitsAfterD
Hàm FormatNumber trả về một biểu thức đã được định dạng dưới dạng giá trị số. FormatNumber( biểu thức [,NumDigitsAfterDecimal [,Inc
Tôi là một lập trình viên xuất sắc, rất giỏi!