通过函数指针间接完美转发?

2024-01-06

让我们考虑一下普通的完美转发:

class Test
{
public:
    Test() = default;
    Test(Test const&) { std::cout << "copy\n"; }
    Test(Test&&)      { std::cout << "move\n"; }
};

void test(Test)
{ }

template <typename T>
void f(T&& t)
{
    test(std::forward<T>(t));
}

int main()
{
    std::cout << "expect: copy\n";
    Test t;
    f(t);
    std::cout << "expect: move\n";
    f(Test());
    return 0;
}

到目前为止一切都很好。但是如果我们现在引入一个函数指针,我就会遇到一个问题,我似乎无法声明普遍的(转发)参考文献 https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers:

    decltype(&f<Test>) ptr = &f<Test>;
    // above produces ordinary r-value references
    // making below fail already on compilation:
    ptr(t);

模板函数指针也会出现问题:

template <typename T>
void(*ptr)(T&& t) = &f<T>; // again resolved to r-value reference

首先,他们也决定纯右值引用,此外他们还定义了一个bunch指针而不是单个指针,使得该方法在类范围内不可用:

class C
{
    template <typename T>
    void(*ptr)(T&& t); // fails (of course...)
};

所以现在的问题是:是否有可能通过函数指针进行间接完美转发?

承认,已经担心答案是'no'(目前又回到左值引用),但仍然希望忽略某个地方的某些东西......


A 转发参考不仅仅是一个假设的概念。它是给特定类型的右值引用的名称,该类型在模板参数推导中具有特殊的推导规则。

具体根据[临时扣除呼叫]/3 https://timsong-cpp.github.io/cppwp/n4861/temp#deduct.call-3.sentence-3:

A 转发参考是对 cv 无限定模板参数的右值引用,该参数不表示类模板的模板参数(在类模板参数推导 ([over.match.class.deduct]) 期间)。如果 P 是转发引用并且参数是左值,则使用类型“对 A 的左值引用”代替 A 进行类型推导。

除了这一特殊规则(以及另一项[温度扣除类型] https://timsong-cpp.github.io/cppwp/n4861/temp#deduct.type-10.sentence-2),转发引用的行为就像任何其他右值引用一样。

特别是在提供模板参数时T,没有发生模板参数推导,直接执行替换。作为替代,应用通常的参考折叠规则。

So f<Test>将产生函数参数Test&&这是一个右值引用并且f<Test&>将产生函数参数Test&(崩溃自&&被应用到Test&).

这些也是在没有显式模板参数的函数调用中为右值参数和左值参数推导的模板参数。如果引用不是转发引用,则T永远不能推导为引用,并且函数参数在替换后始终是右值引用。此次专项调整A引用中提到的允许T被推导为左值引用类型,以便折叠规则也将产生左值引用函数参数。

转发引用只能存在于模板中。模板的函数或特化不能具有转发引用。它们在某种程度上并不是与右值/左值引用不同的引用类别。它们仅通过为参数的不同值类别推导出不同类型并为每个值类别生成不同的专业化来在模板中工作。


因此,由于函数指针必须指向function,而不是函数模板,在获取函数指针时必须决定选择参数值类别的两个特化中的哪一个。

如果需要任何类型的推导,那么函数指针就无法提供该推导。相反,应该使用 lambda 或函子类型,它可以执行推导,并可以根据值类别选择要调用的函数或函数模板特化。

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

通过函数指针间接完美转发? 的相关文章

  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 类型中的属性名称必须是唯一的

    我正在使用 Entity Framework 5 并且有以下实体 public class User public Int32 Id get set public String Username get set public virtual
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐