std::promise 可以由非 POD 对象制成吗?

can an std::promise be made from a non-POD object?

我的应用程序所做的其中一件事是侦听和接收来自套接字的有效负载。我从不想阻止。在收到的每个有效负载上,我想创建一个对象并将其传递给工作线程,直到稍后再忘记它,这就是原型代码的工作方式。但是对于生产代码,我想通过使用方便的异步方法来降低复杂性(我的应用程序很大)。 async 从承诺中获取未来。为此,我需要在下面由 Xxx class 表示的非 POD 对象上创建一个承诺。我看不到有任何方法可以做到这一点(请参阅下面我的示例代码中的错误)。这里用async合适吗?如果是这样,我如何构造一个比 int 更复杂的 promise/future 对象(我看到的所有代码示例都使用 int 或 void):

#include <future>
class Xxx //non-POD object
{
  int i;
public:
  Xxx( int i ) : i( i ) {}
  int GetSquare() { return i * i; }
};

int factorial( std::future< Xxx > f )
{
  int res = 1;
  auto xxx = f.get();
  for( int i = xxx.GetSquare(); i > 1; i-- )
  {
    res *= i;
  }
  return res;
}

int _tmain( int argc, _TCHAR* argv[] )
{
  Xxx xxx( 2 ); // 2 represents one payload from the socket
  std::promise< Xxx > p; // error: no appropriate default constructor available
  std::future< Xxx > f = p.get_future();
  std::future< int > fu = std::async( factorial, std::move( f ) );
  p.set_value( xxx );
  fu.wait();
  return 0;
}

听起来您的实施有问题。应该不需要默认构造函数(根据 [utility.arg.requirements] 的一般库要求),并且 GCC 接受您的代码(在将奇怪的 Microsoftish _tmain 更改为标准 main 之后) .

我会切换到不同的编译器和操作系统。这可能不是你的选择,所以也许你可以给 class 一个默认的构造函数来让它开心。

正如 Mike 已经回答的那样,这绝对是 std::promise 的 Visual C++ 实现中的错误,您正在做的应该有效。

但我很好奇为什么您仍然需要这样做。也许还有一些其他要求您没有显示以保持示例简单,但这是编写该代码的明显方式:

#include <future>

class Xxx //non-POD object
{
  int i;
public:
  Xxx( int i ) : i( i ) {}
  int GetSquare() { return i * i; }
};

int factorial( Xxx xxx )
{
  int res = 1;
  for( int i = xxx.GetSquare(); i > 1; i-- )
  {
    res *= i;
  }
  return res;
}

int main()
{
  Xxx xxx( 2 ); // 2 represents one payload from the socket
  std::future< int > fu = std::async( factorial, std::move( xxx ) );
  int fact = fu.get();
}