C++11:重载无法解析递归 decltype

2023-11-26

在下面的代码中,我尝试构建类型网格。例如,之间float and int,将结果推广为float:

float join(float f, int)   { return f; }
float join(float f, float) { return f; }

然后我介绍一个wrapper type:

template <typename Inner>
struct wrapper
{
  using inner_t = Inner;
  inner_t value;
};

谁的行为与join操作相当自然:

template <typename Inner1, typename Inner2>
auto
join(const wrapper<Inner1>& w1, const wrapper<Inner2>& w2)
  -> wrapper<decltype(join(w1.value, w2.value))>
{
  return {join(w1.value, w2.value)};
}

也可以是joined 为“标量”类型:

template <typename Inner1, typename T2>
auto
join(const wrapper<Inner1>& w1, const T2& value2)
  -> wrapper<decltype(join(w1.value, value2))>
{
  return {join(w1.value, value2)};
}

到目前为止,效果很好,有效。但是,因为在实际情况中我实际上有更多这样的规则,所以我想避免重复规则的数量来表达join操作,因此,我表示join(scalar, wrapper) := join(wrapper, scalar)(事实上​​,我更喜欢类似的东西join(v1, v2) := join(v2, v1),但让我们从更具体的事情开始。):

template <typename T1, typename Inner2>
auto
join(const T1& value1, const wrapper<Inner2>& w2)
  -> decltype(join(w2, value1))
{
  return join(w2, value1);
}

这适用于join(scalar, scalar), join(wrapper, scalar) and join(scalar, wrapper)。但是之后join(wrapper, wrapper)导致 G++ 4.9 和 Clang++ 3.5 的模板函数无限扩展,我不明白。

int main()
{
  int i;
  float f;
  wrapper<float> fr;
  join(f, i);
  join(fr, i);
  join(i, fr);
  join(fr, fr); // Loops.
}

Clang:

clang++-mp-3.5 -std=c++11 bar.cc
bar.cc:21:5: fatal error: recursive template instantiation exceeded maximum depth of
      256
    join(const wrapper<Inner1>& w1, const T2& value2)
    ^
bar.cc:29:5: note: while substituting deduced template arguments into function
      template 'join' [with T1 = wrapper<float>, Inner2 = float]
    join(const T1& value1, const wrapper<Inner2>& w2)
    ^

GCC:

g++-mp-4.9 -std=c++11 bar.cc
bar.cc:30:34: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum) substituting 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = <missing>; Inner2 = <missing>]'
       -> decltype(join(w2, value1))
                                  ^
bar.cc:30:34:   recursively required by substitution of 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = wrapper<float>; Inner2 = float]'
bar.cc:30:34:   required by substitution of 'template<class T1, class Inner2> decltype (join(w2, value1)) join(const T1&, const wrapper<Inner2>&) [with T1 = wrapper<float>; Inner2 = float]'
bar.cc:43:18:   required from here

我不明白为什么重载不会减少递归。到底是怎么回事?可能有一种可能的替代实现(类)模板专门化,但我并不是在寻找替代实现:我想了解这个实现有什么问题。提前致谢。


这有几个问题,其中之一会导致错误。

template <typename Inner1, typename T2>
auto
join(const wrapper<Inner1>& w1, const T2& value2)  // (A)
  -> wrapper<decltype(join(w1.value, value2))>;

名称查找join这里不会通过非限定查找找到相同的函数模板,因为尾随返回类型是声明的一部分,只能找到名称一旦他们have已宣布。但语法允许 ADL 找到相同的函数模板。从属名称的 ADL 稍后执行(从实例化点开始)。

据我了解这个问题,问题来自重载解析:之前decltype(join(w1.value, value2))尝试解析重载时,所有具有该名称的函数模板都需要实例化。对于每个函数模板,都会将一个实例化添加到重载集中(如果实例化成功)。

因此,所有join需要是实例化。实例化包括确定返回类型。对于这个特定的每个实例join函数模板 (A),具有相同模板参数的相同函数模板 (A) 是重载决策集的候选者。也就是说,要确定(A)有哪种返回类型,需要有一个重载决策,这需要确定(A)的返回类型等等。

推导和替换在递归的任何一步中都不会失败,这是唯一的原因not选择此重载是之间的部分排序不同的调用的函数模板join。并且仅检查部分排序作为...的一部分重载解析过程——为时已晚,无法阻止进一步的实例化。

正如错误消息中提到的,此错误是作为实现限制而发生的。因此,它不属于 SFINAE 类别,请参阅解决表达式的 SFINAE 问题。因此,即使不选择此重载,它的存在也会使程序格式错误,就像

struct tag_for_ADL {};

template<class T>
auto foo(T p) -> decltype(foo(p));

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

C++11:重载无法解析递归 decltype 的相关文章

随机推荐

  • 我可以用 d3 附加文字 SVG 元素吗?

    我想用 d3 附加一个文字 SVG 元素 所以而不是写 svg selectAll circle data data enter append circle etc etc 我想做 svg selectAll circle data dat
  • iPhone 中收到警告:NSString 可能不会响应“-JSONValue”

    在我的 iPhone 应用程序中 我正在访问网络服务器以获取数据 这里我使用 JSON 从数据库中检索数据 我收到一条警告 NSString 可能不会响应 JSONValue 如何解决呢 添加这个 import JSON h 在你的顶部 m
  • Dagger2:如果没有 @Provides 注释的方法,则无法提供 ViewModel

    我正在遵循使用的架构Github浏览器示例由谷歌 但在建设项目的过程中却遇到了麻烦 我已经将项目迁移到AndroidX 我已经尝试了 StackOverflow 上的许多答案 但都没有成功 这是我在构建时遇到的构建异常 e windows
  • 如何获取user.config路径中的哈希值?

    我已经安装了 NET应用程序 它的配置位置是 AppData CompanyName ExeName Url hash version user config 我需要得到 hash 来自另一个应用程序的值 根据MSDN user confi
  • 在 Python 的 Decimal 类中设置精度

    我刚刚学习了Python中的Decimal类 在修改十进制数字的精度时遇到了一些问题 代码 from decimal import def main getcontext prec 50 print Decimal 748327402479
  • Resharper 具有多个参数的函数上的右括号缩进

    我在 c 中有一些代码行 Resharper 缩进如下 Console WriteLine Hello this MySuperFunction argument1 argument2 argument3 Console WriteLine
  • TF400813: 用户“”无权访问此资源

    我有自己的私人组织和存储库 我还有多个目录 除了 Microsoft 帐户 目录之外 所有目录都可以工作 我可以使用 Microsoft 帐户目录毫无问题地登录 Azure Devops 我看到了我的组织 我可以浏览我的存储库 代理 管道等
  • 表格单元格中的 CSS 文本溢出?

    我想使用 CSStext overflow在表格单元格中 如果文本太长而无法容纳在一行中 它将用省略号进行剪辑 而不是换行到多行 这可能吗 我试过这个 td overflow hidden text overflow ellipsis wh
  • 如何将 ASP.NET 5 (vnext) 从 Beta5 升级到 Beta6

    从 ASP NET v5 Beta4 升级到 Beta5 有点痛苦 升级到 Beta6 有多难 像这样的备忘单 4 5答案会很方便 升级很顺利 这是备忘单 先决条件 升级到beta6 dnvm upgrade 如果您愿意 请安装 x64 d
  • 如何从java代码调用XSL模板?

    如何从java代码调用XSL模板 请注意 我不需要知道如何在 Java 中通过 XSL 转换 xml 文档 我真正需要的是 我有一些 XSLT 文档 其中包含一个可以执行某些操作的模板 例如
  • 隐藏 iPhone 地址栏,高度为 100%

    关于此的很多帖子 但并不完全适合我的情况 我的页面的灵活尺寸设置为 100 宽度和 100 高度 因此典型的加载滚动功能不起作用 有什么想法或其他解决方案吗 Thanks CSS margin 0 padding 0 html body w
  • Json.NET:用双引号反序列化

    我正在尝试反序列化作为服务响应收到的 json 字符串 客户端是Windows Phone 7 C 语言 我在用Json NET 詹姆斯 牛顿 金反序列化器直接将Json字符串转换为对象 但有时 Json 字符串包含一些带有双引号 的注释信
  • Go(lang) 中的地址空间是什么?

    我尝试了解 Go 中并发编程的基础知识 几乎所有的文章都使用这个词 地址空间 例如 所有 goroutine 共享相同的地址空间 这是什么意思 我尝试从 wiki 理解以下主题 但没有成功 http en wikipedia org wik
  • setTooltipText() 和 android:tooltipText 在 Nougat 中不起作用

    我有一个 ImageButton 当我对我的应用程序进行一些测试时 我发现我无法显示tooltipText在我的带有 Android N 设备的小米 Note 4 中 但它在我的带有 Android O 的三星 S8 上显示得非常好 知道为
  • 找不到中央目录记录的末尾

    我正在使用 C 程序下载 zip 文件 但收到错误 at System IO Compression ZipArchive ReadEndOfCentralDirectory at System IO Compression ZipArch
  • 当方法的签名定义为 Collection 时,为什么方法不能采用 Collection

    我有一个获取 SResource 对象列表的方法 public static List
  • 从 jQuery 调用 ASMX

    我试图从 jQuery 调用 ASMX 方法 但没有成功 以下是我的代码 我不明白我缺少什么 文件Something js function setQuestion ajax type POST data dataType json url
  • rbind data.frames 没有名称

    我想弄清楚为什么rbind加入没有名称的 data frames 时 函数无法按预期工作 这是我的测试 test lt data frame id rep c a b each 3 time rep 1 3 2 black 1 6 whit
  • 将阿拉伯语存储在 SQL 数据库中

    我尝试在 SQL 2008 数据库中存储阿拉伯字符串 但它转换为 问号 为什么 我该怎么办 您需要为 varchar char 列选择阿拉伯排序规则或使用 Unicode nchar nvarchar CREATE TABLE test c
  • C++11:重载无法解析递归 decltype

    在下面的代码中 我尝试构建类型网格 例如 之间float and int 将结果推广为float float join float f int return f float join float f float return f 然后我介绍