2012-01-11 31 views
5

Tôi có một ứng dụng mà tôi đang xây dựng một chức năng, marshal_and_apply, gọi một số chức năng khác (hoặc functor), f với một số đối số. Công việc của marshal_and_apply là áp dụng một số marshaling đặc biệt cho các đối số tùy thuộc vào loại tham số của f.Làm cách nào để kiểm tra các loại tham số của hàm?

Nếu một trong các thông số của f thuộc loại đặc biệt, marshal_me<T>, thì marshal_and_apply sẽ sắp xếp thông số thông qua một số bộ nhớ được phân bổ đặc biệt trước khi chuyển đến f. Để thực hiện việc phân bổ, các yêu cầu lưu trữ của tất cả các tham số phải được biết đến marshal_and_apply trước khi bất kỳ có thể được sắp xếp.


Một số ví dụ:

template<typename Function, typename... Args> 
void marshal_and_apply(Function f, Args... args); 

void func1(int x, int y); 
void func2(marshal_me<int> x, int y); 
void func3(marshal_me<int> x, marshal_me<int> y, marshal_me<int> z); 

// this call would be equivalent to: 
// func1(7,13) 
marshal_and_apply(func1, 7, 13); 

// this call would be equivalent to: 
// auto storage = my_allocator(sizeof(int)); 
// auto x = marshal_me<int>(7, storage); 
// func2(x, 13); 
marshal_and_apply(func2, 7, 13); 

// this call would be equivalent to: 
// auto storage = my_allocator(sizeof(int) + sizeof(int) + sizeof(int)); 
// auto x = marshal_me<int>(7, storage); 
// auto y = marshal_me<int>(13, storage + sizeof(int)); 
// auto z = marshal_me<int>(42, storage + sizeof(int) + sizeof(int)); 
// func3(x,y,z); 
marshal_and_apply(func3, 7, 13, 42); 

Để giải quyết vấn đề này, có vẻ như marshal_and_apply đòi hỏi một cơ chế để kiểm tra các loại thông số f 's. Tôi nghi ngờ điều này là không thể nói chung, nhưng nó có thể có thể nhận ra cho dù một trong một bộ đặc biệt của các loại (trong trường hợp này, marshal_me<T>) là chuyển đổi thành loại của một tham số cụ thể.

Tôi nên xây dựng marshal_and_apply như thế nào?

+0

Trong ví dụ thứ hai của bạn, tôi không thể thấy những gì bạn đã làm với '7'. Ý của bạn là 'auto x = marshal_me (bộ nhớ, 7);' hoặc cái gì đó? –

+0

@AaronMcDaid Có, tôi đã sửa nó. –

+0

Nếu 'marshal_me ' có một hàm tạo lấy 'int' bạn có thể gọi' func2 (7, 13) '. Lợi ích bổ sung nào là trình bao bọc? –

Trả lời

4

Có lẽ một cái gì đó như thế này:

template<typename Function, typename... Args> 
void marshal_and_apply(Function f, Args &&... args) 
{ 
    f(InspectAndModify<Args>::process(sizeof...(Args), std::forward<Args>(args))...); 
} 

Bây giờ xác định:

template <typename T> struct InspectAndModify 
{ 
    static T&& process(unsigned int N, T && t) 
    { 
     return std::forward<T>(t); 
    } 
}; 

template <typename T> struct InspectAndModify<marshal_me<T>> 
{ 
    static T&& process(unsigned int N, marshal_me<T> && m) 
    { 
     /* ... */ 
    } 
}; 

Something hoàn toàn khác nhau: Cách tiếp cận này đầu tiên dissects chữ ký chức năng, và sau đó thực hiện một "tĩnh transform "trên mỗi cặp loại, là nơi bạn có thể chèn chuyên môn marshal_me:

template <typename T> struct marshal_me { marshal_me(T) { } }; 

template <typename To, typename From> struct static_transform; 

template <typename T> struct static_transform<T, T> 
{ 
    static T go(T t) { return t; } 
}; 

template <typename T> struct static_transform<T, T&> 
{ 
    static T go(T & t) { return t; } 
}; 

template <typename T> struct static_transform<marshal_me<T>, T> 
{ 
    static marshal_me<T> go(T && t) { return std::forward<T>(t); } 
}; 

template<typename T, typename... Args> 
struct marshal_impl 
{ 
    template <typename ...Urgs> 
    static T go(T(*f)(Urgs...), Args &&... args) 
    { 
    return f(static_transform<Urgs, Args>::go(std::forward<Args>(args))...); 
    } 
}; 

template<typename Function, typename... Args> 
void marshal_and_apply(Function f, Args &&... args) 
{ 
    marshal_impl<void, Args...>::go(static_cast<typename std::decay<Function>::type>(f), 
            std::forward<Args>(args)...); 
} 
+0

Cảm ơn! Điều đó sẽ sắp xếp công việc, nhưng tôi sợ nó sẽ không giải quyết được ví dụ thứ ba. '' 'InspectAndModify :: process''' cần biết tổng số tham số cần xử lý trước khi nó có thể xử lý bất kỳ tham số nào. –

+0

@JaredHoberock: bạn có thể truyền 'sizeof ... (Args)' làm tham số bổ sung không? –

+0

Chức năng nào? Chữ ký '' 'marshal_and_apply''' là cố định, nhưng nó có thể truyền thông tin thêm vào' '' InspectAndModify :: process'''. –

Các vấn đề liên quan