【问题标题】:Initializer list of RValuesRValues 的初始化列表
【发布时间】:2017-03-30 00:44:01
【问题描述】:

现在我有一个只有一个构造函数的类

ShaderProgram(std::initializer_list<std::reference_wrapper<const Shader>> shaders);

我正在使用引用包装器,因为我不能有引用的 initializer_list 并且我不能复制

此代码有效

    Shader v{ Shader::Type::Vertex, readFile("res/simple.vert") };
    Shader f{ Shader::Type::Fragment, readFile("res/simple.frag") };
    ShaderProgram shader{ v, f };

但这不是

    ShaderProgram shader{ 
        Shader { Shader::Type::Vertex, readFile("res/simple.vert") },
        Shader { Shader::Type::Fragment, readFile("res/simple.frag") }
    };

我应该在这里介绍什么?我想我缺少某种构造函数来处理右值,但我似乎无法让它工作

当前的错误是:

E1776 函数“std::reference_wrapper<_ty>::reference_wrapper(_Ty &&) [with _Ty=const core::graphics::Shader]”(在“c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.10.25017\include\type_traits") 不能被引用——它是一个被删除的 函数渲染引擎 Main.cpp (77)

【问题讨论】:

  • “这不起作用” - 怎么做?你收到什么错误?你能发一个MVCE吗?
  • Here is a MCVE。问题是 std::reference_wrapper 被指定为有一个删除的移动构造函数(不要问我为什么)
  • 在另一个问题中,您说A 是不可复制的。这个问题也是这样吗?如果是这样,那么您应该在问题中包含该信息。
  • 还解释了ShaderProgram构造函数实际上对初始化列表中的东西做了什么。 (它不能保存对它们的引用,因为它们在构造函数调用后被销毁,并且它不能复制它们,因为它们是不可复制的,没有太多选择)
  • @M.M reference_wrapper&lt;T&gt; 没有删除的移动构造函数。它有一个从右值Ts 中删除的构造函数,因为那是不安全的。

标签: c++ c++11 c++14


【解决方案1】:

reference_wrapper 不能从纯右值创建。所以你正在做的事情是不可能的。

在我看来,您的界面似乎有些混乱。一方面,Shader 是不可复制的类型。但另一方面,您似乎想用Shader prvalues 调用ShaderProgram,这将在ShaderProgram 对象构造后立即销毁。

我说,有两个用于ShaderProgram 的接口:一个接受initializer_list&lt;Shader&gt;:这样的用户不会对在函数初始化之后保留他们的Shader 对象不感兴趣。另一个将采用指向Shader 对象的非空指针数组/向量/等。这适用于那些希望在创建程序后保留其Shader 对象的用户。

还可以创建一个可变参数模板,其中您要求所有元素都是Shader 类型。最后一部分(验证所有传递的类型是某种形式的Shader)在没有 C++17 特性的情况下相当困难。

【讨论】:

  • 谢谢。具体情况是,shader 需要在 shaderprogram 构造函数中附加,然后 shaderptogram 需要链接它们,之后可以销毁着色器(但不需要)。现在我已经覆盖了“未销毁”,但我要求的内联选项也很有意义。关于 c++17 功能,您是在谈论概念吗?我是一个模板编程的菜鸟,更喜欢可变参数模板,但我会试一试
  • @PedroDavid:“关于 c++17 的特性,你是在谈论概念吗”。不;概念不在 C++17 中。我特别指的是折叠表达式,它允许你这样做:static_assert(is_same_v&lt;decay_t&lt;Args&gt;&gt;, Shader&gt; &amp;&amp; ... &amp;&amp; true, "An argument type is not a Shader."); 如果没有折叠表达式(或 std::conjunction,这也是 C++17 中的新功能),跨参数包执行条件真的很难。
  • (恢复旧线程)。我刚刚使用可变参数模板(没有折叠表达式)实现了它。这似乎是最好的选择!使用问题。现在我的 ShaderProgram 是模板化的,传递起来很麻烦(除非我模板化一个函数,否则我必须确切知道 ShaderProgram 有多少个 Shader...)。为避免这种情况,我创建了一个返回非模板化 ShaderProgram 的模板化朋友“make_shader_program”,我不知道这是“hack”还是好的做法。
  • 另外,在实施问题中,我还没有访问折叠表达式的权限,所以我使用了this 之类的东西。出现了一个问题,似乎静态转换需要一个 ; (分号)。我在 lambda 表达式中使用 IIFE 解决了它。这似乎很好,但它似乎没有在 gcc 下编译(参数包由于某种原因没有扩展)所以我担心如果我以未定义的行为或其他方式进行中继。
  • 我发现的另一种方法是使用 2 个参数包扩展,一个具有自定义类型特征 (static_assert(are_same...>::value);) 和其他实际做的工作。但试图简化代码我实际上想出了另一个想法。使用 static_cast 而不是 static_assertion 和自定义 type_trait 怎么样?这是好的做法吗?
猜你喜欢
  • 1970-01-01
  • 2016-09-13
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 2011-08-09
  • 1970-01-01
  • 1970-01-01
  • 2015-02-28
相关资源
最近更新 更多