C++11 在c+中转换std::future或std::shared#u future+;11 这听起来很愚蠢,但是C++和C++ 11在它能达到的魔力方面让我吃惊。也许这太远了,但我更喜欢证实我的恐惧,而不是假设它们

C++11 在c+中转换std::future或std::shared#u future+;11 这听起来很愚蠢,但是C++和C++ 11在它能达到的魔力方面让我吃惊。也许这太远了,但我更喜欢证实我的恐惧,而不是假设它们,c++11,casting,future,C++11,Casting,Future,是否可以以任何方式强制转换std::future或std::future\u共享对象 我发现,如果我描述我遇到的具体问题,通常会有所帮助。我基本上是异步加载一些音频和视频,虽然我已经开始使用std::async,我发现它非常有用,但我以前从未使用过futures。从本质上讲,我了解到futures似乎可以很好地处理异常,我希望使异步加载更加健壮。我的crummy程序偶尔会耗尽内存,但在异步调用启动之前,程序不会出现这种情况。解决内存问题完全是另一个问题,目前不是一个可行的解决方案 无论如何,我有

是否可以以任何方式强制转换std::future或std::future\u共享对象

我发现,如果我描述我遇到的具体问题,通常会有所帮助。我基本上是异步加载一些音频和视频,虽然我已经开始使用std::async,我发现它非常有用,但我以前从未使用过futures。从本质上讲,我了解到futures似乎可以很好地处理异常,我希望使异步加载更加健壮。我的crummy程序偶尔会耗尽内存,但在异步调用启动之前,程序不会出现这种情况。解决内存问题完全是另一个问题,目前不是一个可行的解决方案

无论如何,我有两个单独的对象来处理音频(AudioLibrary)和视频(VideoLibrary)的加载,但是由于它们共享许多共性,所以它们都继承自同一个基本对象(BaseLibrary)

这些库中的每个库返回的音频和视频都位于它们自己的音频(AudioTrack)和视频(VideoTrack)容器中,这两个容器也继承自一个公共对象(BaseTrack)

我相信你能看到这一切。我希望在BaseLibrary中发生一些常规异常处理,它将具有一些虚拟函数,如loadMedia。这些将被派生库覆盖。麻烦就这样开始了。我读到指针对象(比如unique_ptr或shared_ptr)不能是协变的,所以仅仅创建一个虚拟方法并不能完全解决这个问题

然而,我希望通过虚拟功能,我仍然能够以某种方式实现我想要的

按照BaseLibrary的思路实现以下功能:

std::shared_future<BaseTrack> BaseLibrary::loadMedia()
std::shared_future<BaseTrack> BaseLibrary::loadMediaHelper()
std::shared\u future BaseLibrary::loadMedia()
std::shared\u future BaseLibrary::loadMediaHelper()
然后AudioLibrary将实现

std::shared_future<AudioTrack> AudioLibrary::loadAudio()
std::shared\u未来音频库::loadAudio()
此函数使用BaseLibrary中的函数,但返回其自身特定类型的音轨,而不是基本音轨

这有可能吗

更新1:

多亏了这些评论和回答,我明白了如何实现我想要的,但我还有几个问题没有解决。我认为通过非常明确的方式来解决这些问题会容易得多。实际上,我正在使用shared_ptr,因为许多对象正在使用加载的音频和视频,所以我有以下类型的def:

typedef std::shared_ptr<BaseTrack> BaseTrackPtr;
typedef std::shared_ptr<AudioTrack> AudioTrackPtr;
typedef std::shared_ptr BaseTrackPtr;
typedef std::共享_ptr AudioTrackPtr;
当然,AudioTrack继承自BaseTrack。根据给出的建议,我有一个可编译(缩写)的代码结构,BaseLibrary的代码结构如下:

class BaseLibrary {
  virtual std::shared_future<BaseTrackPtr> loadMedia();
  virtual std::shared_future<BaseTrackPtr> loadMediaHelper() = 0;
}

std::shared_future<BaseTrackPtr> BaseLibrary::loadMedia()
{
// Place code to catch exceptions coming through the std::future here.
// Call the loadMediaHelper via async - loadMediaHelper is overwritten in the inherited libraries.
}
类库{
虚拟std::shared_future loadMedia();
虚拟std::shared_future loadMediaHelper()=0;
}
std::shared_future BaseLibrary::loadMedia()
{
//将捕获通过std::future出现的异常的代码放在此处。
//通过异步调用loadMediaHelper-loadMediaHelper在继承的库中被覆盖。
}
音频图书馆:

class AudioLibrary : public BaseLibrary {
public:
  virtual std::shared_future<AudioTrackPtr> loadAudio();
protected:
  virtual std::shared_future<BaseTrackPtr> loadMediaHelper();
}

std::shared_future<AudioTrackPtr> AudioLibrary::loadAudio()
{
  std::shared_future<BaseTrackPtr> futureBaseTrackPtr = loadMedia();
  return std::async( std::launch::deferred, [=]() {
    return AudioTrackPtr( std::static_pointer_cast<AudioTrack>( futureBaseTrackPtr.get() ) );
} );
}

std::shared_future<BaseTrackPtr> AudioLibrary::loadMediaHelper()
{
  // Place specific audio loading code here
}
类音频库:公共基本库{
公众:
虚拟std::shared_future loadAudio();
受保护的:
虚拟std::shared_future loadMediaHelper();
}
std::shared_future AudioLibrary::loadAudio()
{
std::shared_future futureBaseTrackPtr=loadMedia();
返回std::async(std::launch::deferred,[=](){
返回AudioTrackPtr(std::static_pointer_cast(futureBaseTrackPtr.get());
} );
}
std::shared_future AudioLibrary::loadMediaHelper()
{
//在此放置特定的音频加载代码
}
这个结构允许我在一个地方捕获任何视频/音频加载异常,并且还返回正确的音频/视频对象,而不是需要重铸的基本对象

我目前的两个问题如下:

  • 让BaseLibrary中的loadMedia中的异步调用为std::launch::deferred,然后让loadAudio(或loadVideo)中的异步调用为std::launch::async,这不是最好的做法吗?我基本上希望加载立即开始,但也可以等到外部异步调用执行后再开始。。。?这有意义吗
  • 最后,这是不是很丑陋?我的一部分感觉是,我正在充分利用C++11所提供的所有优点、共享资源、未来等等。但我对未来也很陌生所以。。。我不知道在共享的未来放置共享指针是否。。。奇怪

所以你有这样的想法:

class BaseLibrary
{
public:
    virtual ~BaseLibrary() {}
    virtual std::shared_future<std::unique_ptr<BaseTrack>> loadMedia() = 0;
};

class AudioLibrary : public BaseLibrary
{
public:
    std::shared_future<AudioTrack> loadAudio();
    std::shared_future<std::unique_ptr<BaseTrack>> loadMedia() override;
};

与此相关,您可以在加载方法中公开策略,以获得所需的灵活性(在最高级别只能使用一个
std::launch::async
)。我认为在
将来的
中放置智能指针没有任何问题。
std::shared_future<std::unique_ptr<BaseTrack>> AudioLibrary::loadMedia()
{
    auto futureAudioTrack = loadAudio();

    return std::async(std::launch::deferred,
        [=]{
            std::unique_ptr<BaseTrack> res =
                make_unique<AudioTrack>(futureAudioTrack.get());
            return res;
        });
}