我们正在尝试生成一个将执行异步调用的库组件。 由于各种原因,这需要具有类似C的接口,因此我们提供了大量静态函数作为库的接口。
我们还需要用户控制内存。所以大多数函数看起来像
int myLibFunction(void* data, size_t data_size);
我正在尝试用更智能的Future对象替换它,以便我们不使用void指针,以便在线程之间同步对数据的访问。理想情况下,呼叫看起来像:
Future<T> {
T m_data;
}
static int myLibDoJob1(Future<Func1Data>& data);
static int myLibDoJob2(Future<Func2Data>& data);
main()
{
Func1Data m_data;
Func2Data m_data2;
Future<Func1Data> future1(m_data);
Future<Func2Data> future2(m_data2);
int ret=0;
ret = myLibDoJob1(future1);
ret = myLibDoJob2(future2);
}
这是一个相当干净的界面,界面在编译时强制类型安全。但是我遇到的问题是我正在创建一个内部执行的作业队列。但是由于Futures的大小不同,我无法创建std:队列,我原本希望能够创建一个std :: queue,其中Job包含Future *但是这是无效的。
我也试过让Job包含Future,其中所有Data类派生自ParentData也无济于事。
问题非常类似于拥有智能指针容器的问题。由于我工作的团队的性质,我将无法在库外暴露任何增强对象,如果我使Future多态,我将被一个板球棒追逐。
重要的是,库的用户端代码可以控制数据的实际位置。
此致 伊恩
答案 0 :(得分:3)
您将使用C ++进行多态,或者您将使用void*
重新实现多态性。解决问题的最简单方法是给Future<T>
一个不依赖于T的基类。通常我这样做:
class Future {};
template<class T>
class FutureOf : public Future {};
然后,您可以创建Future*
的容器并具有一些类型安全性。
答案 1 :(得分:0)
目前还不完全清楚你要做什么。但是,如果我理解正确的话,你有一堆遗留函数,并且你试图将每个函数包装在(模板)类中,并为它提供特定于类型的数据。像下面这样的东西可以做你想要的吗?
#include <iostream>
#include <list>
class AbstractFuture
{
public:
virtual int compute() const = 0;
};
// Encapsulates function and data
template <typename F, typename T>
class Future : public AbstractFuture
{
public:
Future(F func, T x) : func_(func), x_(x) {}
virtual int compute() const { return func_(x_); };
private:
const F func_;
const T x_;
};
// Helper function template, to save all the explicit <> nonsense
// you'd need otherwise
template <typename F, typename T>
AbstractFuture *createFuture(F func, T x) { return new Future<F,T>(func, x); }
// Some data types
typedef float Func1Data;
typedef double Func2Data;
// Dummy function implementations
static int myLibDoJob1(const Func1Data& data) { return 5; }
static int myLibDoJob2(const Func2Data& data) { return 7; }
int main()
{
// Data for each Future
Func1Data x1 = 0;
Func2Data x2 = 0;
// Create some Futures (note, the function template makes this type-safe)
AbstractFuture *p1 = createFuture(myLibDoJob1, x1);
AbstractFuture *p2 = createFuture(myLibDoJob2, x2);
// Put into a container (of pointers to base class)
std::list<AbstractFuture *> futures;
futures.push_back(p1);
futures.push_back(p2);
// Demonstrate polymorphism works
for (std::list<AbstractFuture *>::const_iterator it = futures.begin();
it != futures.end(); ++it)
{
std::cout << (*it)->compute() << std::endl;
}
delete p1;
delete p2;
return 0;
}
这可以通过智能指针更干净地完成,但这个想法应该成立。