c++ - 松耦合隐式转换

标签 c++ boost-mpl enable-if

当类型在语义上等价时,隐式转换非常有用。例如,假设两个库实现了相同的类型,但在不同的命名空间中。或者只是一种几乎相同的类型,除了一些语义糖在这里和那里。现在,您不能将一种类型传递给旨在使用另一种类型的函数(在其中一个库中),除非该函数是模板。如果不是,您必须以某种方式将一种类型转换为另一种类型。这应该是微不足道的(否则类型毕竟不是那么相同!)但是显式调用转换会使您的代码膨胀,其中大部分是无意义的函数调用。虽然这样的转换函数实际上可能会复制一些值,但从高级“程序员”的角度来看,它们基本上什么都不做。

隐式转换构造函数和运算符显然会有所帮助,但它们会引入耦合,因此其中一种类型必须了解另一种类型。通常,至少在处理库时,情况并非如此,因为其中一种类型的存在使另一种变得多余。此外,您不能总是更改库。

现在我看到了两个关于如何在用户代码中进行隐式转换的选项:

  1. 第一个是提供代理类型,为所有涉及的类型实现转换运算符和转换构造函数(和分配),并始终使用它。

  2. 第二个需要对库进行最小的更改,但具有很大的灵 active : 为每个涉及的类型添加一个转换构造函数,可以选择在外部启用。

例如,为 A 类型添加一个构造函数:

template <class T> A(
  const T& src,
  typename boost::enable_if<conversion_enabled<T,A>>::type* ignore=0
)
{
  *this = convert(src);
}

还有一个模板

template <class X, class Y>
struct conversion_enabled : public boost::mpl::false_ {};

默认禁用隐式转换。

然后要启用两种类型之间的转换,请专门化模板:

template <> struct conversion_enabled<OtherA, A> : public boost::mpl::true_ {};

并实现一个可以通过ADL找到的convert函数。

我个人更喜欢使用第二种变体,除非有强烈的反对意见。

现在回到实际问题:为隐式转换关联类型的首选方法是什么?我的建议是好主意吗?这两种方法都有缺点吗?允许这样的转换危险吗?当他们的类型很可能在他们最有可能使用的软件中被复制时,库实现者一般是否应该提供第二种方法(我在这里考虑 3d 渲染中间件,其中大多数包都实现了 3D vector )。

最佳答案

如果我愿意的话,我更喜欢你的“代理”方法而不是其他选项。

事实上,我发现这是所有开发领域中的一个重大问题,以至于我倾向于避免在与该特定库的交互之外使用任何库特定构造。一个例子可能是处理各种不同库中的事件/信号。我已经选择了 boost 作为我自己项目代码的integral 的东西,所以我非常有目的地使用 boost::signals2 在我自己的项目代码中进行所有通信。然后我将接口(interface)写入我正在使用的 UI 库。

另一个例子是字符串。那里的每一个该死的 UI 库都重新发明了字符串。我的所有模型和数据代码都使用标准版本,并且我为我的 UI 包装器提供了在此类类型中工作的接口(interface)……仅在我直接与 UI 组件交互的那一点转换为 UI 特定版本。

这确实意味着我无法利用各种独立但相似的构造提供的大量功能,并且我正在编写大量额外的代码来处理这些转换,但这是非常值得的,因为如果我发现更好的库和/或需要切换平台,这样做变得容易得多,因为我没有让这些东西在所有事情中都杂乱无章。

所以基本上,我更喜欢代理方法,因为我已经在这样做了。我在抽象层中工作,使我与我正在使用的任何特定库保持距离,并使用与所述库交互所需的细节对这些抽象进行子类化。我一直在这样做,所以想知道我想在两个第三方库之间共享信息的一些小区域基本上已经得到解答。

关于c++ - 松耦合隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4702002/

相关文章:

c++ - CPP 字符串的字符串分词器?

c++ - 如何将 type 和 mpl::vector 连接到一个新的 vector 中

c++ - ostream 运算符的编译时重载

c++ - 在构造函数中 boost enable_if

c++ - boost::mpl::map 类型和 char 字符串

c++ - 如果每个参数都可转换为特定类型,则启用构造函数

c++ - 如何在 C++ 中读取/写入数据到 excel 2007?

c++ - 打开相对于已执行模块的文件

c++ - 评估为 "void..."的非类型参数包不是非法的吗?

c++ - 有没有办法绑定(bind) template<template> 参数?