Python chúng tôi codebase có mã số liệu liên quan đến trông như thế này:Thực hành tốt nhất + cú pháp để thực hiện một "contextmanager" trong C++
class Timer:
def __enter__(self, name):
self.name = name
self.start = time.time()
def __exit__(self):
elapsed = time.time() - self.start
log.info('%s took %f seconds' % (self.name, elapsed))
...
with Timer('foo'):
do some work
with Timer('bar') as named_timer:
do some work
named_timer.some_mutative_method()
do some more work
Trong thuật ngữ Python, bộ đếm thời gian là một contextmanager.
Bây giờ, chúng tôi muốn thực hiện điều tương tự trong C++, với cú pháp đẹp như nhau. Thật không may, C++ không có with
. Vì vậy, "rõ ràng" thành ngữ sẽ là (RAII cổ điển)
class Timer {
Timer(std::string name) : name_(std::move(name)) {}
~Timer() { /* ... */ }
};
if (true) {
Timer t("foo");
do some work
}
if (true) {
Timer named_timer("bar");
do some work
named_timer.some_mutative_method();
do some more work
}
Nhưng điều này là cực kỳ xấu xí muối cú pháp: đó là nhiều dòng dài hơn nó cần phải được, chúng tôi đã giới thiệu một tên t
cho timer "vô danh" của chúng tôi (và mã phá vỡ âm thầm nếu chúng ta quên tên đó) ... nó chỉ là xấu xí.
Một số thành ngữ cú pháp mà mọi người đã sử dụng để xử lý "contextmanagers" trong C++ là gì?
Tôi đã nghĩ đến ý tưởng lạm dụng này, làm giảm dòng-count nhưng không thoát khỏi tên t
:
// give Timer an implicit always-true conversion to bool
if (auto t = Timer("foo")) {
do some work
}
Hoặc quái vật kiến trúc này, mà tôi don' thậm chí không tin tưởng bản thân mình để sử dụng một cách chính xác:
Timer("foo", [&](auto&) {
do some work
});
Timer("bar", [&](auto& named_timer) {
do some work
named_timer.some_mutative_method();
do some more work
});
nơi các nhà xây dựng của Timer
actuall y gọi lambda đã cho (với đối số *this
) và ghi nhật ký tất cả trong một lần.
Tuy nhiên, những ý tưởng này có vẻ như là "thực tiễn tốt nhất". Giúp tôi ra đây!
Một cách khác để cụm từ câu hỏi có thể là: Nếu bạn được thiết kế std::lock_guard
từ đầu, làm thế nào bạn sẽ làm điều đó để loại bỏ càng nhiều càng tốt soạn sẵn? lock_guard
là một ví dụ hoàn hảo của bối cảnh ngữ cảnh: đó là một tiện ích, đó là bản chất RAII, và bạn hầu như không bao giờ muốn bận tâm đặt tên nó.
Bạn có thể tạo khối không giới thiệu 'if (true)' – Jarod42
Giải pháp chung chỉ là raii. Là câu hỏi cụ thể của bạn làm thế nào để viết một bộ đếm thời gian để in thời gian trôi qua ở cuối? – Barry
Tôi thực sự nghĩ rằng giải pháp lambda của bạn là tốt đẹp. – JorenHeit