Sử dụng decorator function trong C++
TIL
608
White

Manh Truong Tuan viết ngày 14/04/2018

Vài hôm trước, khi phải giải quyết một task liên quan đến việc phải thêm 1 vài thay đổi khá lớn cho một loạt các function có sẵn thì mình chợt nhớ ra trong python có decorator function để làm những thứ kiểu như thế.
Decorator tạm hiểu nhanh là sẽ lây input là 1 function, thêm thắt 1 số tính năng cho function đó rồi return function mới.
Và mình đã kiếm giải pháp tương tự dùng cho C++.
Trong ví dụ cho giải pháp này, decorator sẽ thêm tính năng đo thời gian vào cho hàm input.

  • Trong C++, decorator function mới sẽ là một call object :
 template <class> struct ExeTime;

// Execution time decorator
// R là return type, Args là một loạt các kiểu dữ liệu cho tham số của hàm
template <class R, class... Args>
struct ExeTime<R(Args ...)> {

public:
     // Constructor cho Callable object này chính là input function
    ExeTime(std::function<R(Args...)> func): f_(func) { } 

    // operator () sẽ được dùng để gọi như một hàm thông thường
    R operator ()(Args ... args) {
        std::chrono::time_point<std::chrono::system_clock> start, end;
        std::chrono::duration<double> elasped;

        start = std::chrono::system_clock::now();

       // Gọi input function tại đây
        R result = f_(args...);    

        end = std::chrono::system_clock::now();
        elasped = end - start;
        std::cout << elasped.count() << " seconds" << std::endl;

        return result;
    }   

private:
    std::function<R(Args ...)> f_; 
};

C++11 giới thiệu tính năng mới là varidic templates (typename ...) cho phép input nhiều tham số trong template
Class trên lấy đầu vào là function , và có operator() để sử dung như 1 function call.
Tới đây ta có thể dùng như sau

 // Example input function
 long long foo_loop(int n) {
    long long sum = 0;
    int i = 0;
    while(i < n) {
        sum += i;
        i += 1;
    }
    return sum;
}

int main() {
    ExeTime<long long(int)> decorator(foo_loop);
    // Goi ham decorator
   decorator(1000000);

}

Tuy nhiên có thể thấy là cách dùng decorator trên không được đẹp lắm, ta phải khai báo kiểu dữ liệu tham số và return của hàm input cho ExeTime.
Trong C++ 11 có khái niệm là template argument deduction tức là template sẽ tự nội suy được kiểu dữ liệu từ input đầu vào, tuy nhiên nó sẽ không áp dụng được cho template class như ExeTime mà chỉ áp dụng cho template function thôi. Vậy ta sẽ viết 1 function có input là foo_loop để tạo ra 1 object ExeTime

template <class R, class... Args>
ExeTime<R(Args ...)> make_decorator(R (*f)(Args ...)) {
    return ExeTime<R(Args...)>(std::function<R(Args...)>(f));    
}

Bây giờ, muốn tạo ra decorator thì chỉ cần gọi hàm make_decorator, gần đẹp được bằng python

 int main() {
    auto decorator = make_decorator(foo_loop);    
    cout <<  decorator(1000000) << endl;

    return 0;
}
Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Manh Truong Tuan

8 bài viết.
6 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
3 3
Sử dụng Terminal hiệu quả hơn với tmux (Link) 1. Cài đặt bash $ sudo E addaptrepository ppa:pirho/dev $ sudo aptget update $ sudo aptget install...
Manh Truong Tuan viết gần 2 năm trước
3 3
White
2 0
Bài toán là 1 mô hình kiểu mạng xã hội đơn giản, trong đó user nhấn vào 1 nút Add friend hoặc Follow để cho 1 user khác vào danh sách theo dõi ( để...
Manh Truong Tuan viết gần 2 năm trước
2 0
White
1 0
Note về Regex Tổng hợp lại những kiến thức cơ bản về Regex mà mình đã được thực hành tại regexone.com Tìm kiếm đúng một chuỗi Cách này gần như ...
Manh Truong Tuan viết gần 2 năm trước
1 0
Bài viết liên quan
White
0 2
fCC: Technical Documentation Page note So I have finished the HTML part of this exercise and I want to come here to lament about the lengthy HTML ...
HungHayHo viết 2 tháng trước
0 2
White
19 1
Toán tử XOR có tính chất: + A XOR A = 0 + 0 XOR A = A Với tính chất này, có thể cài đặt bài toán sau với độ phức tạp O(N) về runtime, và với O(1)...
kiennt viết gần 2 năm trước
19 1
White
1 1
Chào mọi người, hôm nay mình viết một bài TIL nhỏ về cách lấy độ phân giải của màn hình hiện tại đang sử dụng. xdpyinfo | grep dimensions Kết quả...
namtx viết 1 năm trước
1 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
8 bài viết.
6 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!