折叠表达式:替换特定类型但转发所有其他类型:如何实现这一点?

2023-12-09

我试图替换折叠表达式中的特定类型,同时简单地转发所有其他类型,但失败了。

As std::forward需要显式模板专门化我尝试提供另一组模板化重载,但是这些尚未考虑重载解决方案如果这有效的话,无论如何都会导致不明确的函数调用。

第二次尝试是专门化std::forward但尝试已经失败了...

模拟std::forward;实际上复制了 GCC 的实现,只是添加了一些输出来看看发生了什么:

namespace test
{
template<typename T>
constexpr T&&
fw(typename std::remove_reference<T>::type& t) noexcept
{
    std::cout << "standard" << std::endl;
    return static_cast<T&&>(t);
}

template<typename T>
constexpr T&&
fw(typename std::remove_reference<T>::type&& t) noexcept
{
    std::cout << "standard (r-value)" << std::endl;
    static_assert
    (
            !std::is_lvalue_reference<T>::value,
            "template argument substituting T is an lvalue reference type"
    );
    return static_cast<T&&>(t);
}
}

我的测试如下:

class Test
{
public:
    template <typename ... T>
    void test(T&& ... t)
    {
        using test::fw;

///////////////////////////////////////////////////
        ( g(fw<T>(t)), ... );
///////////////////////////////////////////////////
    }

private:
    template <typename T>
    T&& g(T&& t)
    {
        std::cout << "g: r-value: " << t << '\n' << std::endl;
        return std::move(t);
    }
    template <typename T>
    T& g(T& t)
    {
        std::cout << "g: l-value " << t << '\n' << std::endl;
        return t;
    }
};

int main()
{
    int nn = 10;
    Test t;
    std::string s("daal");
    t.test(12, nn, std::string("alda"), s);

    return 0;
}

按原样(以及我失败的尝试,请参阅链接的问题)输出是:

standard
g: r-value: 12

standard
g: l-value 10

standard
g: r-value: alda

standard
g: l-value daal

所需的输出类似于:

standard
g: r-value: 12

standard
g: l-value 10

specialised (r-value)
g: r-value: alda

specialised (l-value)
g: l-value daal

(参考类型是可选的。)

我怎样才能做到这一点?

目的是保留折叠表达式 – Icould解决问题递归的模板和适当的重载,但这不是这里的目的。这是出于纯粹好奇的问题,因为我已经解决了我的实际问题(通过发现实际上根本不需要可变参数模板,因此可以使用if constexpr相反,在函数内部,因此也不再有 XY 问题)。


if constexpr包装器内是解决方案的关键(感谢@用户17732522对于提示),但是它需要与第二个结合std::forward并且不只接收 r 值[s|参考]decltype(auto)以及。这样的函数甚至可以包含在 Test 类中,这是额外需要但可选的功能(测试函数中的 lambda 可能看起来像......)。

解决方案可能如下所示:

class Test
{
    template <typename T>
///////////////////////////////////////////////////
// note: decltype(auto)!
///////////////////////////////////////////////////
    static decltype(auto) fw(T&& t)
    {
        if constexpr(std::is_same_v<std::remove_const_t<std::remove_reference_t<T>>, std::string>)
        {
            std::cout << "std::string: ";
            if constexpr(std::is_lvalue_reference_v<decltype(t)>)
            {
                std::cout << "l-value\n";
                std::string s;
                s.reserve(t.length() + 2);
                s += '\'';
                s += t;
                s += '\'';
                return s;
            }
            else
            {
                std::cout << "r-value\n";
                t.reserve(t.length() + 2);
                t.insert(t.begin(), '\'');
                t.push_back('\'');
                return t;
            }
        }
        else
        {
            std::cout << "default\n";
            return std::forward<T>(t);
        }
    }

public:
    template <typename ... T>
    void test(T&& ... t)
    {
///////////////////////////////////////////////////
// note: yet another call to std::forward!
///////////////////////////////////////////////////
        ( g(fw(std::forward<T>(t))), ... );
    }

private:
    template <typename T>
    T&& g(T&& t)
    {
        std::cout << "g: r-value: " << t << '\n' << std::endl;
        return std::move(t);
    }
    template <typename T>
    T& g(T& t)
    {
        std::cout << "g: l-value " << t << '\n' << std::endl;
        return t;
    }
};

int main()
{
    int n = 10;
    Test t;
    std::string s("daal");
    t.test(12, n, std::string("alda"), s);
    std::cout << std::endl;

    return 0;
}

(修改字符串模拟转换为另一种类型......)

收到的输出(根据需要):

default
g: r-value: 12

default
g: l-value 10

std::string: r-value
g: l-value 'alda'

std::string: l-value
g: r-value: 'daal'

(auto代替decltype(auto) prints g: r-value四次!)

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

折叠表达式:替换特定类型但转发所有其他类型:如何实现这一点? 的相关文章

  • boost::multi_index_container 复合键中的 equal_range 与比较运算符

    我正在尝试从多索引容器查询结果 其中值类型是三个元素的结构 第一个值已给出 但第二个和第三个值必须大于或小于查询参数 经过搜索后 我发现必须实现自定义密钥提取器 并且这里的一些链接建议相同 但我无法实现它 boost multi index
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • SSH 主机密钥指纹与模式 C# WinSCP 不匹配

    我尝试通过 WinSCP 使用 C 连接到 FTPS 服务器 但收到此错误 SSH 主机密钥指纹 与模式不匹配 经过大量研究 我相信这与密钥的长度有关 当使用 服务器和协议信息 下的界面进行连接时 我从 WinSCP 获得的密钥是xx xx
  • C# 中可空类型是什么?

    当我们必须使用nullable输入 C net 任何人都可以举例说明 可空类型 何时使用可空类型 https web archive org web http broadcast oreilly com 2010 11 understand
  • 使用 Google Analytics API 在 C# 中显示信息

    我一整天都在寻找一个好的解决方案 但谷歌发展得太快了 我找不到有效的解决方案 我想做的是 我有一个 Web 应用程序 它有一个管理部分 用户需要登录才能查看信息 在本节中 我想显示来自 GA 的一些数据 例如某些特定网址的综合浏览量 因为我
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 编译的表达式树会泄漏吗?

    根据我的理解 JIT 代码在程序运行时永远不会从内存中释放 这是否意味着重复调用 Compile 表达式树上会泄漏内存吗 这意味着仅在静态构造函数中编译表达式树或以其他方式缓存它们 这可能不那么简单 正确的 他们可能是GCed Lambda
  • 是否有比 lex/flex 更好(更现代)的工具来生成 C++ 分词器?

    我最近将源文件解析添加到现有工具中 该工具从复杂的命令行参数生成输出文件 命令行参数变得如此复杂 以至于我们开始允许它们作为一个文件提供 该文件被解析为一个非常大的命令行 但语法仍然很尴尬 因此我添加了使用更合理的语法解析源文件的功能 我使
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 网络参考共享类

    我用 Java 编写了一些 SOAP Web 服务 在 JBoss 5 1 上运行 其中两个共享一个类 AddressTO Web 服务在我的 ApplycationServer 上正确部署 一切都很顺利 直到我尝试在我的 C 客户端中使用
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • GDK3/GTK3窗口更新的精确定时

    我有一个使用 GTK 用 C 语言编写的应用程序 尽管该语言对于这个问题可能并不重要 这个应用程序有全屏gtk window与单个gtk drawing area 对于绘图区域 我已经通过注册了一个刻度回调gtk widget add ti
  • 在Linux中使用C/C++获取机器序列号和CPU ID

    在Linux系统中如何获取机器序列号和CPU ID 示例代码受到高度赞赏 Here http lxr linux no linux v2 6 39 arch x86 include asm processor h L173Linux 内核似
  • 窗体最大化时自动缩放子控件

    有没有办法在最大化屏幕或更改分辨率时使 Windows 窗体上的所有内容自动缩放 我发现手动缩放它是正确的 但是当切换分辨率时我每次都必须更改它 this AutoScaleDimensions new System Drawing Siz
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • C# / Java | AES256加密/解密

    我想加密通过 Java C 套接字 Java 服务器 C 客户端 发送的所有数据 我想使用 AES256 但我无法让 Java 和 C 生成相同的加密代码 任何人都可以给我两个示例 1 个 Java 示例和 1 个 C 示例 它们会生成相同
  • 如何使用 PHP 使用 google API 获取用户“contactid”

    我正在尝试使用 google API 3 0 获取用户联系人以及所有用户详细信息 我能够获得包含用户详细信息的 JSON 响应 url https www google com m8 feeds contacts default full
  • 使用 JavaScript 从数组中删除对象

    如何从数组中删除对象 我希望删除包含名称的对象Kristian from someArray 例如 someArray name Kristian lines 2 5 10 name John lines 1 19 26 96 我想实现 s
  • 切换内部片段

    我用 NavigationView 创建了一个 Activity 用切换按钮打开 public class MainActivity extends AppCompatActivity implements NavigationView O
  • ImportError: libcublas.so.9.0: 无法打开共享对象文件: 在 Ubuntu 16.04.03 上安装张量流时没有这样的文件或目录

    我正在尝试安装带有 cuda 和 gpu 支持的tensorflow 当我尝试导入它时 出现以下错误 Traceback most recent call last File
  • 更改默认短信应用意图在 Android 10 上不起作用

    您好 我正在努力将我的应用程序兼容性更新为 android 10 和 11 之前我将我的应用程序设置为默认短信应用程序并从我的应用程序接收和发送新短信 更改默认短信应用程序的意图在 android 10 以下工作正常 但它不是显示更改 An
  • java中的最小值不起作用

    我需要帮助 因为我的脑细胞无法发现这个程序出了什么问题 这是代码 import java util public class student public static void main String args Scanner sc ne
  • 正则表达式对非捕获组的帮助

    肯定是重复的 但我找不到它 我正在使用一个组来匹配重复的子字符串 然而 我不希望这群人被抓获 这似乎是一个矛盾 明确地说 假设我想找到跟随全大写子集字符串的 3 个精确副本的任何字符 为了 s hjgABABABfgfBBdqCCCugDD
  • 递归清空多个文件的命令

    我想递归地清除给定目录的许多日志文件的内容 而不删除每个文件 用一个简单的命令就可以实现吗 我知道我能做到 gt logs logfile log一份一份的 但是该文件夹中有很多日志 这并不简单 顺便说一句 我正在使用 macOS Sier
  • super() 在构造函数中意味着什么? [复制]

    这个问题在这里已经有答案了 代码是做什么的 super 在构造函数内部做什么 例如 这是我的类的构造函数 public abstract class Rectangle extends AbstractShape private doubl
  • 在Python中查找函数的参数

    我希望能够询问班级的 init 方法的参数是什么 简单的方法如下 cls init func code co varnames code co argcount 但是 如果类有任何装饰器 那么这将不起作用 它将给出装饰器返回的函数的参数列表
  • 检查 xslt 中的条件

    下面是输入 XML 小大 对于较大的输入 XML 以及输出 xml 表示抱歉
  • 访问 Ansible playbook 中的清单主机变量

    在 Ansible 2 1 中 我有一个角色被需要访问主机文件变量的剧本调用 关于如何访问它有什么想法吗 我正在尝试访问ansible ssh host in the test1以下清单的部分host file test1 test 1 a
  • 全栈 NestJS 应用程序中的 OAuth2 流程

    另一个 OAuth2 问题在其他地方没有完全涵盖 我使用 NestJS 后端 React 前端 Passport 和我自己的数据库进行身份验证 尝试添加一个 OAuth2 身份提供商 Google 我将 NestJS 应用程序配置为 OAu
  • Grails:更改 hibernate 方言时 SQL 语法错误

    我正在将 Grails 与 mySQL 数据库一起使用 并且尝试更改数据库引擎 据我研究 这可以最好地做到 dialect org hibernate dialect MyDialect 在 DataSource groovy 配置中 但是
  • 在 Regex/Javascript 中将一个字符交换为另一个字符

    我想做类似的事情 var a This is an A B pattern ABABA a replace A B a replace B A 并让它返回 gt 这是 B A 模式 BABAB 代替 gt 这是一个 A A 模式 AAAAA
  • ElasticSearch:我们可以在索引期间同时应用 n-gram 和语言分析器吗

    非常感谢 Random 我已将映射修改如下 为了进行测试 我使用 电影 作为索引类型 注意 我还添加了 search analyzer 如果没有这个 我就无法得到正确的结果 但是我对使用 search analyzer 有以下疑问 1 我们
  • Tapestry:字符编码问题

    我有一个 Tapestry 应用程序 它从表单中检索数据 将其写入数据库 然后显示结果 只要不使用特殊字符 一切都可以正常工作 例如 文本 Test 将导致 Test 我猜这个问题与错误的字符编码设置有关 Tapestry java 类 C
  • 删除多个实体上的表行拆分时出错

    我想删除拆分为两个实体的表行 如果我尝试删除主要实体 如果之前我没有使用以下命令加载相关的其他实体 则会收到错误消息context Entry Reference 当我要删除整行时 之前检索相关实体是不是有点愚蠢 如果我继续评论 我会收到以
  • 折叠表达式:替换特定类型但转发所有其他类型:如何实现这一点?

    我试图替换折叠表达式中的特定类型 同时简单地转发所有其他类型 但失败了 As std forward需要显式模板专门化我尝试提供另一组模板化重载 但是这些尚未考虑重载解决方案如果这有效的话 无论如何都会导致不明确的函数调用 第二次尝试是专门