c++ - 实现可以转换为 Stream<U> 的 Stream<T>,其中 U 是 T 的基数

标签 c++ pointers casting

我正在尝试实现一个通用的对象输入流。即,实现的接口(interface)或轻量级代理。实现的细节是未知的,即我的库的用户可以编写自己的流,比如 protobuf 消息,将它传递到我的库并返回,比如字符串流或任何其他流。我想保持流的通用接口(interface),以便用户可以编写自己的转换并构建转换管道。

流的接口(interface)应该是这样的:

template <typename T>
class Stream {
public:
    T* input();
}

在每次通话中,input()如果流为空,应返回流中的下一个对象或空指针。

问题是我想要Stream<T>可转换为 Stream<U>如果T*可转换为 U* .

我不成功的尝试是像这样使用指向实现的指针:

class StreamImplBase {
public:
    virtual void* input_raw() = 0;
}

template <typename T>
class StreamImpl: public StreamImplBase {
public:
    void* input_raw() final { return input(); }
    virtual T* input() = 0;
}

template <typename T>
class Stream {
    StreamImplBase* impl;
public:
    Stream(StreamImpl<T>* impl): impl(impl) {}
    T* input() { return static_cast<T*>(impl->input_raw()); }
}

来自 StreamImpl<T> 的构造函数保证 void*input_raw() 返回被类型转换收购Tvoid* ,因此 static_cast<T*>是安全的。

但是,如果我进行任何转换,这个说法就不会成立。即建筑Stream<T>来自 StreamImpl<U>即使 U* 也不安全可转换为 T* .

所以我的问题是,我该如何处理这个问题?

我看到了下一个可能性:

  • 在流中存储转换器(例如 std::function<T*(void*)> )并在每次转换时更新它。这似乎不必要地昂贵;

  • 存储 static_cast<U*>((T*)0) 的结果并将此结果添加到从 input_raw() 获得的指针中.这似乎是不必要的危险;

  • 添加第二个模板参数OrigT和存储StreamImpl<OrigT>*而不是存储 StreamImplBase* .这将限制类的可能应用,我想避免这种情况;

  • 使用 dynamic_cast不是一种选择,因为不能 dynamic_cast来自 void* .

还有其他可能吗?其他人如何实现这样的东西?


这是一个用例。假设我们有一个 protobuf 消息 X .我想要这个工作:

Stream<X> stream = ...;
Stream<google::protobuf::Message> raw_stream = stream;

同样,我不知道如何Stream<X>实现。我所知道的是它包含一个共享指针,指向生成消息的某些实现。

最佳答案

这个:

template <typename T>
class Stream {
public:
  T* input();
};

是一个只有一个操作的对象,它接受 0 个参数并返回一个 T*。 .

这是这样的:

std::function<T*()>

诚然,您可以像 stream() 一样调用它而不是 stream.input() .

使用第二种解决方案,如果 UT 的基础, 然后你可以将上面的转换为 std::function<U*()> .这可以解决您的问题。

我个人不认为输入 .input在您的流名称和 () 之间值得做很多工作。

其他人已经完成的类型删除是最好的类型删除。

关于c++ - 实现可以转换为 Stream<U> 的 Stream<T>,其中 U 是 T 的基数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50071350/

相关文章:

c# - LINQ 查询抛出 InvalidCastException?

c++ - 从 0 到最大值的 uint64_t 键的最佳哈希函数是什么?

c++ - 关于 OpenGL 的问题和将 C 转换为 C++ 的过程

c - 为什么我可以更新指向(常量)字符串文字的指针?

c - C 赋值和参数传递会导致隐式转换,还是我们应该显式转换?

arrays - Swift 3 - 转换值时总是得到 nil

c++ - 在 Linux 上使用纯 C 项目中用 C++ 编写的库?

c++ - 删除同一个对象两次

c - 指针未设置为 NULL (C)

c - 为什么这些词不附加在 C 中?