【问题标题】:C++ compile-type resource owner assertionC++ 编译型资源所有者断言
【发布时间】:2014-08-11 04:11:22
【问题描述】:
class Resource;

class Device
{
    ...
public:
    Resource createResource();

    bindResource(const Resource&);
};

int main()
{
    Device dev;
    Device oops;

    auto res = dev.createResource();

    dev.bindResource(res); // Okay; dev created this resource

    oops.bindResource(res); // Error: oops did not create this resource
}

Program does not compile

这可以在编译时完全完成,没有运行时开销和类似的语法吗? 例如,设备是 Direct3D 渲染器的抽象;我们不能共享一些资源,如果我们尝试应该是编译时错误。

【问题讨论】:

  • 不,编译器无法跟踪资源的使用位置,因此您必须在运行时进行。

标签: c++ resources compile-time ownership


【解决方案1】:

有一个解决方法,它使用__COUNTER__ 宏。虽然标准没有提供,但 MSVC 和 GCC 都支持它。此宏与一个整数值相关,每次您在翻译单元中使用此宏时,该整数值都会递增。所以,实现如下:

// Device.h
#define DEVICE Device<__COUNTER__>

template<int N>
class Device
{
public:
    class Resource{};
    Resource createResource() { return Resource(); }
    void bindResource(const Resource&) {}
};

如您所见,Resource 类现在在 Device 类中声明。 Device 类的所有实例都应使用 DEVICE 宏声明。现在,devoops 实例被实例化为不同类型的对象。 devDevice&lt;0&gt;oopsDevice&lt;1&gt;。并且分别res现在是Device&lt;0&gt;::Resource,oops绑定不了。

但是,这种方法有以下缺点(至少):
1) 将设备作为函数参数传递是一个问题。为了保证编译时检查,所有处理设备的函数也应该是模板。这可能会导致严重的代码膨胀。
2) 如果你声明了一个DEVICE类型的数组(例如,DEVICE devices[10]),所有的设备将是相同类型的,因此,将能够相互绑定资源。
3) __COUNTER__ 宏仅通过单个翻译单元提供唯一值。如果你在一个翻译单元的开头声明dev,在第二个翻译单元的开头声明oops,它们的类型将是相同的,oops将能够绑定dev的资源。 4) __COUNTER__ 不是标准提供的。

毕竟,我不建议您使用此解决方法,它可能仅用于教育目的:)

【讨论】:

  • 啊,有趣,COUNTER 宏对我来说是新的。我曾尝试通过 int ID 进行模板化,但正如您提出的那样,在这种情况下,将为每个新 ID 复制代码。尝试了一些继承技巧,它变得非常混乱。
  • 我讨厌很多 API 都有这样的复杂性,理论上可以在编译时检查它们,因为它们是逻辑错误,但对于我们拥有的语言,它就不会发生。
  • 哦,对不起,我不能投票给你;我没有所需的声誉。
猜你喜欢
  • 1970-01-01
  • 2022-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多