Tôi đã dành vài ngày qua để cố gắng tạo ra một trình bao bọc chung cho các con trỏ hàm trong C++ và tôi đã quản lý để giải quyết gần như mọi thanh vấn đề đơn lẻ. Mục tiêu chính của tôi với điều này là để có thể chỉ đơn giản gọi một đối tượng như một hàm với một con trỏ hàm được lưu trữ nội bộ. Nếu con trỏ trỏ đến đâu đó thì nó sẽ gọi nó như bình thường trong khi một con trỏ null sẽ không gọi hàm đó và nó sẽ tiếp tục như thể không có gì xảy ra. Tôi dự định sử dụng chủ yếu cho các mục đích chức năng gọi lại, nơi mà tôi có thể sẽ không quan tâm nếu hàm đó được gọi hay không và chỉ muốn tạo thành một hành động. Nó hoạt động gần như hoàn hảo với những điều sau:Sử dụng gói tham số '...' của C làm giá trị mẫu C++?
template<typename T>
class Action;
template<typename TReturn, typename ... TArgs>
class Action<TReturn(TArgs...)> {
public:
//! Define a type for the Action object
typedef TReturn(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TReturn& pReturn, TArgs ... pArgs) const { if (!mPointer) return false; pReturn = mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
template<typename ... TArgs>
class Action<void(TArgs...)> {
public:
//! Define a type for the Action object
typedef void(*signature)(TArgs...);
//! Constructors
inline Action(const signature& pFunc = nullptr) : mPointer(pFunc) {}
inline Action(const Action& pCopy) : mPointer(pCopy.mPointer) {}
//! Operator Call
inline bool operator() (TArgs ... pArgs) const { if (!mPointer) return false; mPointer(pArgs...); return true; }
//! Operators
inline Action& operator=(const Action& pCopy) { mPointer = pCopy.mPointer; return *this; }
inline Action& operator=(const signature& pFunc) { mPointer = pFunc; return *this; }
inline operator bool() const { return (mPointer != nullptr); }
private:
//! Store a pointer to the callback function
signature mPointer;
};
Tuy nhiên, tôi cảm thấy tình huống có khả năng sử dụng trình bao bọc này là đầu ra của thông tin gỡ lỗi hoặc văn bản được định dạng. Điều này có thể thông qua các hàm do người dùng định nghĩa hoặc các hàm sẵn có như printf. Để khớp với chữ ký của printf, Hành động sẽ được tạo như:
Action<int(const char*, ...)> callback = printf;
và nó có thể hoạt động giống như cách hành động khác. Vấn đề tôi đang tìm kiếm là '...' sẽ buộc chữ ký mẫu không phù hợp với một trong hai chuyên môn, thay vào đó là chữ ký đầu tiên chỉ là mẫu thử nghiệm.
Tôi hoàn toàn có thể hiểu tại sao điều này không hiệu quả và tại sao trình biên dịch không thể xử lý việc tạo lớp được yêu cầu nhưng tôi hy vọng rằng ai đó ở đây sẽ biết bất kỳ cách lén lút nào để đạt được điều này hoặc tương tự. Bất kỳ trợ giúp sẽ được nhiều đánh giá cao, nhờ :)
Tại sao không sử dụng 'std :: function'? – StoryTeller
Mục đích của 'Hành động' là gì? Bạn có yêu cầu gì về việc bạn không thể sử dụng ['std :: function'] (http://en.cppreference.com/w/cpp/utility/functional/function)? 'Hành động' giải quyết vấn đề gì' std :: function' không có vấn đề gì? –
https://stackoverflow.com/questions/18370396/why-cant-stdfunction-bind-to-c-style-variadic-functions đưa ra một số bình luận, về cách đạt được gần như thế này. Tôi nghĩ rằng đối với mỗi hàm variadic, bạn sẽ cần một lớp cụ thể để giúp bạn, và hy vọng có một biến thể v * của hàm bạn có thể gọi. – mksteve