命名空间中的模板函数会导致错误

2023-11-27

假设以下代码:

#include <iostream>

template<typename T>
struct Link
{
    Link(T&& val) : val(std::forward<T>(val)) {}

    T val;
};

template<typename T>
std::ostream& operator<<(std::ostream& out, const Link<T>& link)
{
    out << "Link(" << link.val << ")";
    return out;
}

template<typename T>
auto MakeLink(T&& val) -> Link<T>
{
    return {std::forward<T>(val)};
}

namespace Utils {
template<typename Any>
constexpr auto RemoveLinks(const Any& any) -> const Any&
{
    return any;
}

template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val))
{
    return RemoveLinks(link.val);
}

} /* Utils */

int main()
{
    int k = 10;

    auto link = MakeLink(MakeLink(k));

    std::cout << link << std::endl;
    std::cout << Utils::RemoveLinks(link) << std::endl;
}

由于某种原因我无法理解,它会生成以下编译错误g++-4.8:

/home/allan/Codes/expr.cpp: In instantiation of ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const int&]’:
/home/allan/Codes/expr.cpp:88:32:   required from ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = Link<int&>; decltype (Utils::RemoveLinks(link.val)) = const int&]’
/home/allan/Codes/expr.cpp:100:41:   required from here
/home/allan/Codes/expr.cpp:88:32: error: invalid initialization of reference of type ‘const Link<int&>&’ from expression of type ‘const int’
     return RemoveLinks(link.val);
                                ^
/home/allan/Codes/expr.cpp:89:1: error: body of constexpr function ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const Link<int&>&]’ not a return-statement
 }
 ^
/home/allan/Codes/expr.cpp: In function ‘constexpr decltype (Utils::RemoveLinks(link.val)) Utils::RemoveLinks(const Link<T>&) [with T = int&; decltype (Utils::RemoveLinks(link.val)) = const int&]’:
/home/allan/Codes/expr.cpp:89:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

而 clang 3.3 给出:

test.cc:34:12: error: reference to type 'const Link<int &>' could not bind to an lvalue of type 'const int'
return RemoveLinks(link.val);
       ^~~~~~~~~~~~~~~~~~~~~
test.cc:46:25: note: in instantiation of function template specialization 'Utils::RemoveLinks<Link<int &> >' requested here
std::cout << Utils::RemoveLinks(link) << std::endl;

但是,如果命名空间Utils被删除,然后它编译没有错误(gcc 和 clang),并且执行输出:

Link(Link(10))
10

为什么要定义这些模板函数(RemoveLinks)在命名空间中会导致此类错误?


此问题是声明点 (1) 与依赖名称查找 (2) 相结合的问题的结果。

(1)在声明中

template<typename T>
constexpr auto RemoveLinks(const Link<T>& link) -> decltype(RemoveLinks(link.val))

名字RemoveLinks,或者更准确地说,这种超载RemoveLinks,仅可见在完整的声明符之后根据 [basic.scope.pdecl]/1。这尾随返回类型是声明符的一部分,按照 [dcl.decl]/4。另请参阅这个答案.

(2)在表达式中RemoveLinks(link.val), 名字RemoveLinks取决于 [temp.dep]/1,如link.val是依赖的。

如果我们现在查找依赖名称是如何解析的,我们会发现 [temp.dep.res]:

在解析从属名称时,会考虑以下来源的名称:

  • 在模板定义时可见的声明。
  • 来自与来自实例化上下文和定义上下文的函数参数类型相关联的命名空间的声明。

第一个项目符号没有找到第二个过载RemoveLinks由于声明点 (1)。第二个没有找到重载,因为名称空间Util不与任何参数相关联。这就是为什么将所有内容都放在全局命名空间或命名空间中Util按预期工作(实例).

出于同样的原因,使用合格的 ID in the 尾随返回类型 (like -> decltype(Util::RemoveLinks(link.val))在这里没有帮助。

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

命名空间中的模板函数会导致错误 的相关文章

随机推荐

  • M_PI 为负值的 CGAffineTransformMakeRotation

    我在用着CGAffineTransformMakeRotation旋转一个UIView在动画块内 我想将其逆时针旋转180 但是当我把 myView animateWithDuration 0 5 myView transform CGAf
  • 关于 Laravel 5.1 安全性

    我是 Laravel 5 1 开发项目的新手 我想了解如何避免安全风险 Laravel 可以保护哪些类型的攻击 什么样的攻击 Laravel 是不安全的 使用中间件是处理授权的好方法 我知道 Laravel 对于 CSRF 攻击是安全的 有
  • pthread:一个 printf 语句在子线程中打印两次

    这是我的第一个 pthread 程序 我不知道为什么 printf 语句在子线程中打印两次 int x 1 void func void p x x 1 printf tid ld x is d n pthread self x retur
  • 如何从列表中删除空列表(Java)

    我已经搜索过这个 但它是用其他语言编写的 例如Python或R 我在列表中有列表 我想删除空列表 例如 abc def ghi jkl mno 我想 abc def ghi jkl mno 如何从列表中删除空列表 谢谢 你也可以尝试这个 l
  • 操作码 (APC/XCache)、Zend、Doctrine 和自动加载器

    我正在尝试使用 APC 或 XCache 作为操作码来缓存我的 php 页面 我将它与 Zend 和 Doctrine 一起使用 但自动加载器出现问题 如果我尝试使用 APC 我会得到以下信息 Fatal error spl autoloa
  • 实体框架和 SQLite,终极操作方法

    我正在尝试让 Entity Framework 6 4 4 2020 年夏季的最新版本 与 SQLite 1 0 113 1 也是 2020 年夏季的最新版本 一起工作 我找到了很多关于如何执行此操作的信息 但这些信息并不总是有帮助 它们常
  • Android 模拟器实例不显示“允许 USB 调试”确认以进行身份​​验证

    我正在尝试在 Android Studio 的 Android 模拟器中运行我的移动应用程序 当我运行该应用程序时 它会提示我选择模拟器实例 当我选择模拟器实例时 应用程序的构建将启动 并且所选的模拟器将启动 构建完成后 Android S
  • 从数据框中插入 RMySQL

    我正在尝试使用 RMySQL 将数据添加到 MySQL 表 我只需要一次添加一行 但它不起作用 我想做的就是这个 dbGetQuery con INSERT INTO names VALUES data 1 1 data 1 2 所以我正在
  • 新创建的 TFS 2010 迭代不可见

    我已经在 TFS 2010 中创建了一个新的迭代 并且不想在新的故事和查询中使用它 但是 迭代不会显示在新的故事窗口中 刷新VS 重新启动VS 切换到其他项目 没有任何帮助 我是团队项目中的项目管理员 并使用我尝试使用它的同一用户创建了迭代
  • 反应原生 Flatlist 导航

    我收到错误 类型错误 无法读取未定义的属性 导航 我不明白如何将导航组件传递给每个子组件 因此当用户按下某个项目时 它可以使用 React Navigation 导航到 employeeEdit 组件 我是新手 如果这是显而易见的 我很抱歉
  • Hibernate Session 在 ConstraintViolationException 后失效

    在抛出约束违反异常后 是否有任何方法可以继续使用线程绑定的休眠会话 我在这里举一个简短的例子 Parent other service load 33 loads a new parent try Parent p new Parent p
  • 将参数传递给 PrimeFaces 星级评定组件?

    我正在尝试利用星级评定来自 PrimeFaces 的组件 但是 它不允许您传入参数 这使得我无法进行查找以从数据库中获取我想要评分的实体 我尝试过类似的事情 但没有成功
  • 在 PHP 中将标题转换为 url 兼容模式的最佳方法?

    http domain name 1 As Low As 10 Downpayment Free Golf Membership 上面的url会报告400 bad request 如何将此类标题转换为用户友好的标题good要求 您可能想使用
  • 显示/隐藏片段并以编程方式更改可见性属性

    这是一个由两部分组成的问题 我所拥有的是一个 3 片段布局 其中当用户点击另一个片段中找到的按钮时 会动态添加第三个片段 FragmentC 然后 添加后 第三个片段有一个最大化 最小化它的按钮 UPDATE 滚动到最后查看SOLUTION
  • 什么是 XML 属性 xmlns:app?

    XML 可以很好地用于 xmlns app http schemas android com apk res auto 但看不到最大字符数 xmlns app http schemas android com tools 这是由 Andro
  • 尝试将 AutoMapper 用于具有子集合的模型,在 Asp.Net MVC 3 中出现 null 错误

    我对 AutoMapper 完全陌生 我有一个如下所示的视图 using Html BeginForm null null FormMethod Post new enctype multipart form data Html Valid
  • 如何在 Windows 上用 Perl 创建图表?

    如何使用 Perl 创建图表 我正在运行创建文本报告的预定作业 我想将其移至下一步 用于管理 并创建一些与之相关的图表 这可能 可行吗 如果我能以某种方式使用 Office 来完成此操作 那就太好了 更新 我将按此顺序调查的解决方案 Spr
  • 如何使用 PHP 在给定的日期范围和时间生成 .ics 文件 [关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我试图找到一种有效的方法 根据给定的日期范围 开始日期 结束日期 和提醒时间 使用 PH
  • 离子3|将 InAppBrowser 添加到提供程序时遇到问题

    我需要打开一个指向我的 Ionic 3 项目的链接 当我用 google 搜索时 我看到了 InAppBrowser 插件 实际上这个链接中只有一张图片 所以如果您知道任何其他获取它的方法或直接显示这张图片 这对我来说就足够了 我所做的一切
  • 命名空间中的模板函数会导致错误

    假设以下代码 include