C++ 元编程中的 typedef 与公共继承

2024-04-03

免责声明:这个问题与继承而不是 typedef https://stackoverflow.com/questions/441744/inheritance-instead-of-typedef到目前为止我找不到任何类似的问题

我喜欢玩 C++ 模板元编程(主要是在家里,有时我在工作中轻轻介绍它,但我不希望该程序变得只有那些不费心去学习它的人才能阅读),但是我一直在每当出现问题时,编译器错误都会让你很恼火。

问题在于,c++ 模板元编程当然是基于模板的,因此每当您在深度嵌套的模板结构中遇到编译器错误时,您都必须在 10 行错误消息中挖掘出自己的方法。我什至养成了在文本编辑器中复制/粘贴消息的习惯,然后缩进消息以获得某种结构,直到我了解实际发生的情况,这增加了跟踪错误本身的一些工作。

据我所知,问题主要是由于编译器及其输出 typedef 的方式造成的(还有其他问题,例如嵌套深度,但实际上并不是编译器的错误)。即将推出的 C++0x 宣布了一些很酷的功能,例如可变参数模板或类型推导(自动),但我真的希望有更好的错误消息来启动。使用模板元编程可能会很痛苦,我确实想知道当更多的人真正使用它们时,这会变成什么样子。

我已经替换了代码中的一些 typedef,并改用继承。

typedef partition<AnyType> MyArg;

struct MyArg2: partition<AnyType> {};

这并不需要输入更多的字符,而且在我看来,这并不影响可读性。事实上,它甚至可能更具可读性,因为它保证声明的新类型出现在靠近左边距的位置,而不是位于右侧未确定的偏移处。

然而这又涉及到另一个问题。为了确保我没有做任何愚蠢的事情,我经常像这样编写模板函数/类:

template <class T> T& get(partition<T>&);

这样我就确信只能为合适的对象调用它。

特别是当重载运算符(例如运算符+)时,您需要某种方法来缩小运算符的范围,或者冒着被调用 int 等操作的风险。

但是,如果这适用于 typedef'ed 类型,因为它只是一个别名。它肯定不适用于继承......

对于函数,可以简单地使用CRTP http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

template <class Derived, class T> partition;

template <class Derived, class T> T& get(partition<Derived,T>&);

这允许在编译器使用公共继承之前知道用于调用该方法的“真实”类型。应该注意的是,这减少了必须调用该特定函数的机会,因为编译器必须执行转换,但到目前为止我从未注意到任何问题。

此问题的另一种解决方案是向我的类型添加“标签”属性,以区分它们,然后依靠SFINAE http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error.

struct partition_tag {};

template <class T> struct partition { typedef partition_tag tag; ... };

template <class T>
typename boost::enable_if<
  boost::same_type<
    typename T::tag,
    partition_tag
  >,
  T&
>::type
get(T&)
{
  ...
}

不过,它需要更多的输入,特别是如果在不同的地方声明和定义函数/方法(如果我不打扰的话,我的界面很快就会变得混乱)。然而,当涉及到类时,由于没有执行类型转换,所以它确实变得更加复杂:

template <class T>
class MyClass { /* stuff */ };

// Use of boost::enable_if

template <class T, class Enable = void>
class MyClass { /* empty */ };

template <class T>
class MyClass <
  T,
  boost::enable_if<
    boost::same_type<
      typename T::tag,
      partition_tag
    >
  >
>
{
  /* useful stuff here */
};

// OR use of the static assert

template <class T>
class MyClass
{
  BOOST_STATIC_ASSERT((/*this comparison of tags...*/));
};

我倾向于使用更多的“静态断言”而不是“enable_if”,我认为当我在一段时间后回来时它更具可读性。

好吧,基本上我还没有下定决心,我仍在尝试这里公开的不同技术。

你使用 typedef 还是继承? 如何限制方法/函数的范围或以其他方式控制提供给它们(以及类)的参数类型?

当然,如果可能的话,我想要更多个人喜好。如果有充分的理由使用某种特定技术,我宁愿知道它!

EDIT:

我正在浏览 stackoverflow,刚刚从 Boost.MPL 中找到了这个 perl,我完全忘记了:

BOOST_MPL_ASSERT_MSG http://www.boost.org/doc/libs/1_39_0/libs/mpl/doc/refmanual/assert-msg.html

这个想法是你给宏 3 个参数:

  • 要检查的条件
  • 应用于在错误消息中显示的消息(C++ 标识符)
  • 涉及的类型列表(作为元组)

它可能对代码自我文档和更好的错误输出有很大帮助。


您想要做的是显式检查作为模板参数传递的类型是否提供必要的概念。由于缺少被 C++0X 抛弃的概念功能(因此成为 C++1X 的罪魁祸首之一),因此很难进行适当的概念检查。自 20 世纪 90 年代以来,人们曾多次尝试在没有语言支持的情况下创建概念检查库,但基本上,所有这些所取得的成就都是为了表明,为了做得正确,概念需要成为核心语言的一个功能,而不是成为核心语言的一个功能。而不是仅包含库的功能。

我没有找到你的推导而不是想法typedef并使用enable_if非常吸引人。正如您自己所说,它通常只是为了更好的编译器错误消息而掩盖实际代码。

我发现静态断言要好得多。它不需要改变实际的代码,我们都习惯在算法中进行断言检查,并且如果我们想理解实际的算法,就学会在心里跳过它们,它可能会产生更好的错误消息,并且它将延续到 C ++1X 更好,这将有一个static_assert(完全包含类设计者提供的错误消息)内置于语言中。 (我猜测BOOST_STATIC_ASSERT只需使用内置的static_assert如果可以的话。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 元编程中的 typedef 与公共继承 的相关文章

随机推荐

  • Powershell 将行转置为列

    有人可以帮我将行转置为列吗 需要将机器名称转置到列中 结束时间必须排序 lt MachineName TotalDataSizeBytes ActualStartTime EndTime FinalJobStatus SERVER1 322
  • 如何从 uitableviewcell 显示 uidatepicker [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 询问代码的问题必须对所解决的问题表现出最低限度的了解 包括尝试的解决方案 为什么不起作用以及预期结果 也可以看看 Stack Overfl
  • 如何在 Spring 中查看 SOAP 请求的 XML 输出?

    我是 Spring SOAP 请求的新手 我想查看 SOAP 请求的最终 XML 输出 其中包括 SOAP 标头和 SOAP 信封 在调试时我到达了这段代码 sendSourceAndReceiveToResult partnerURI s
  • Xamarin Forms Flex 布局大小调整问题

    在我的 Xamarin Forms 应用程序中 我需要在另一个 Flex 布局内有一个 Flex 布局 这是因为 我的应用程序中需要有两列 一列占据屏幕的 80 另一列占据屏幕的 20 我使用具有两个子级的 FlexLayout 为此设置了
  • Xcode 12.4 中未找到框架 FIRAnalyticsConnector

    在 Xcode 12 4 中更新 pod 后出现 找不到框架 FIRAnalyticsConnector 错误 我已经清理并重建了该项目 但它仍保留在那里 我应该怎么办 转到您的项目目标Build Settings gt 搜索FIRAnal
  • 每次迁移后都需要重新启动 Heroku 吗?

    最近我遇到了一个问题 我的数据库方案更改没有反映在 Heroku PG 上 我仔细检查了一下 发现迁移和种子都成功了 更奇怪的是 数据库方案更改在暂存的 Heroku 部署上运行良好 在完全相同的迁移 种子之后 经过一番搜索后 我了解到您应
  • PHP 中每个文件只有一个或多个函数?

    每当我用 php 设计我的应用程序时 我都会遇到这个问题 这确实让我头疼 我不知道是否应该为每个函数创建单独的文件 例如 用于验证特定表单的函数 好吧 有人可能会认为这没有意义 因为我必须单独包含每个文件 这可能会导致应用程序更慢 但我仍然
  • C++ - 检测超出范围的访问

    我想分析我的 C 代码以查找向量和数组中的错误访问 超出范围访问 是否有工具可以实现这一点 提前致谢 如果您使用的是 gcc 则可以使用定义的 GLIBCXX DEBUG 和 GLIBXX DEBUG PEDATIC 进行编译 如果请求越界
  • 如何修改此 sed awk 命令以便输出到所选文件?

    我正在使用这个答案中的最后一个命令https stackoverflow com a 54818581 80353 https stackoverflow com a 54818581 80353 cap cd tmp rm f vtt y
  • 对 AngularJS 依赖注入不一致感到困惑

    我是新来的angular js 并浏览了几个教程 包括此处的所有教程代码学校 http campus codeschool com courses shaping up with angular js intro 我发现它们非常有用 并且学
  • Google Play 开发者控制台:支持的 Android 设备:0

    我尝试过多次上传 我还查看了有关同一问题的许多其他问题 在我的物理设备上运行良好 但上传到 google play 时显示它支持 0 个设备
  • 为什么我会在 .NET 的 StartsWith 中看到这种意外行为?

    这一定是一个 NET 错误 对吧 KonNy StartsWith Kon 返回 false 同时 KonNy StartsWith Ko and KonN StartsWith Kon 返回真 我在这里缺少什么吗 重复评论 我不太了解 N
  • 使用 fql 检查 Facebook 用户是否喜欢某个页面

    我想检查登录用户是否喜欢指定的页面 下面是我的代码 fql pageid SELECT url site id FROM object url WHERE url IN http developers facebook com api pa
  • 将本地分支合并到远程分支而不是master?

    我有一个本地分支 A 但远程存储库中尚不存在 我在远程仓库中还有一个远程分支 B 如何将本地更改合并到远程分支 如果分支 B 在本地 您可以在本地合并 A 到 B 然后将 B 推送到远程 git checkout B git merge A
  • ASP.NET 中的简单 Web 部件显示为空白页

    我正在尝试开发 Web 部件VS 2008 WinXP 我创建了一个网站项目 并在默认表单中添加了几个 Web 部件default aspx
  • 无法通过curl访问github

    尝试使用以下命令访问 github 失败 并出现验证失败错误 我应该怎么做才能解决这个问题 C software curl 7 23 1 win64 ssl sspi gt curl i https api github com curl
  • 在 Bash 中分割逗号分隔的字符串

    我有这个文件 里面有 20k IP 104 20 15 220 104 20 61 219 104 20 62 219 104 20 73 221 104 20 74 221 104 20 14 220 104 20 15 220 104
  • C# 奇怪的 WPF 组合框行为

    I have simple window This is what happens when I click ComboBox List appears in upper left corner of screen instead of u
  • 构建 Erlang 服务器场(用于业余爱好项目)最便宜的方法是什么? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 假设我们有一个 本质上并行 的问题需要用 Erlang 软件来解决 我们有很多并行进程 每个进程都执行顺序代码 不是数字运算 并且我们向它们投入的 C
  • C++ 元编程中的 typedef 与公共继承

    免责声明 这个问题与继承而不是 typedef https stackoverflow com questions 441744 inheritance instead of typedef到目前为止我找不到任何类似的问题 我喜欢玩 C 模