- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 C++ 中,我们无法创建引用容器:
std::vector<int&> vri;
In instantiation of ‘class __gnu_cxx::new_allocator<int&>’:
required from ‘class std::allocator<int&>’
required from ‘struct std::_Vector_base<int&, std::allocator<int&> >’
required from ‘class std::vector<int&>’
required from here
error: forming pointer to reference type ‘int&’
typedef _Tp* pointer;
^~~~~~~
内部实现需要创建一个指向所包含类型的指针,这会导致指向引用禁止类型的指针。
幸运的是, std::reference_wrapper
存在:
int x{1}, y{2}, z{3};
std::vector<std::reference_wrapper<int>> vr{x, y, z};
for (auto &v : vr)
++v;
std::cout << x << ' ' << y << ' ' << z << '\n';
上面的代码显示2 3 4
.
我正在开发一个 C++ 过滤器实用程序,例如过滤器 where
接收一个容器并返回 std::reference_wrapper
到满足条件的包含对象:
template <typename container_t> auto range(const container_t &container)
{ return std::tuple{std::begin(container), std::end(container)}; };
template <typename container_t, typename predicate_t>
auto where(const container_t &container, predicate_t predicate)
{
auto [b, e] = range(container);
using type = std::remove_reference_t<decltype(*b)>;
using reference = std::reference_wrapper<type>;
std::vector<reference> result{};
std::copy_if(b, e, std::back_inserter(result), predicate);
return result;
}
下面的代码显示2 3 6 7
:
int main()
{
std::vector v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto &x : where(v, [](auto n){ return n & 0b10; }))
std::cout << x << ' ';
return 0;
}
但是我在链接过滤器时遇到问题:
for (const auto &x :
where(where(v, [](auto n){ return n & 0b10; }), [](auto n){ return n & 0b1; })) {
std::cout << x << ' ';
}
no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘const std::reference_wrapper<const std::reference_wrapper<const int> >’)
std::cout << x << ' ';
~~~~~~~~~~^~~~
内部where
返回std::vector<std::refernce_wrapper<int>>
,因此外部将使用 std::vector<std::refernce_wrapper<const std::refernce_wrapper<const int>>>
.
为了解决这个问题,我尝试创建一个打开 std::reference_wrapper<T>
的模板。 :
template <typename type_t>
struct unwrap
{
using type = type_t;
};
template <typename type_t>
struct unwrap<std::reference_wrapper<type_t>>
{
using type = type_t;
};
template <typename type_t>
using unwrap_t = typename unwrap<type_t>::type;
到目前为止,它看起来正在工作:
int main()
{
using ri = std::reference_wrapper<int>;
using rf = std::reference_wrapper<float>;
using rri = std::reference_wrapper<ri>;
using rrri = std::reference_wrapper<rri>;
std::cout
<< typeid(int).name() << '\t' << typeid(unwrap_t<int>).name() << '\n'
<< typeid(float).name() << '\t' << typeid(unwrap_t<float>).name() << '\n'
<< typeid(ri).name() << '\t' << typeid(unwrap_t<ri>).name() << '\n'
<< typeid(rf).name() << '\t' << typeid(unwrap_t<rf>).name() << '\n'
<< typeid(rri).name() << '\t' << typeid(unwrap_t<rri>).name() << '\n'
<< typeid(rrri).name() << '\t' << typeid(unwrap_t<rrri>).name();
return 0;
}
它产生正确的 mangled names :
i i
f f
St17reference_wrapperIiE i
St17reference_wrapperIfE f
St17reference_wrapperIS_IiEE St17reference_wrapperIiE
St17reference_wrapperIS_IS_IiEEE St17reference_wrapperIS_IiEE
整数和浮点( int
、 float
)保持不变,整数和浮点包装器展开,嵌套包装器展开一层。
但是在 where
里面不起作用:
template <typename container_t, typename predicate_t>
auto where(const container_t &container, predicate_t predicate)
{
auto [b, e] = range(container);
using type = unwrap_t<std::remove_reference_t<decltype(*b)>>;
// ^^^^^^^^ <--- Unwraps iterator's inner type
using reference = std::reference_wrapper<type>;
std::vector<reference> result{};
std::copy_if(b, e, std::back_inserter(result), predicate);
// Debug
std::cout
<< __PRETTY_FUNCTION__ << "\n"
<< '\t' << "decltype(*b) = " << typeid(decltype(*b)).name() << '\n'
<< '\t' << "unwrap *b = " << typeid(unwrap_t<decltype(*b)>).name() << '\n'
<< '\t' << "type = " << typeid(type).name() << '\n'
<< '\t' << "reference = " << typeid(reference).name() << '\n'
<< '\t' << "unwrap type = " << typeid(unwrap_t<type>).name() << '\n';
return result;
}
int main()
{
std::vector v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for (const auto &x :
where(where(v, [](auto n){ return n & 0b10; }), [](auto n){ return n & 0b1; })) {
std::cout << &x << ' ';
}
return 0;
}
调试登录到where
显示解包器在第一次调用时起作用(它对类型没有任何作用),但在第二次调用时不起作用:
auto where(const container_t&, predicate_t) [with container_t = std::vector<int, std::allocator<int> >; predicate_t = main()::<lambda(auto:1)>]
decltype(*b) = i
unwrap *b = i
type = i
reference = St17reference_wrapperIKiE
unwrap type = i
auto where(const container_t&, predicate_t) [with container_t = std::vector<std::reference_wrapper<const int>, std::allocator<std::reference_wrapper<const int> > >; predicate_t = main()::<lambda(auto:2)>]
decltype(*b) = St17reference_wrapperIKiE
unwrap *b = St17reference_wrapperIKiE
type = St17reference_wrapperIKiE
reference = St17reference_wrapperIKS_IKiEE
unwrap type = St17reference_wrapperIKiE
在内部调用中,输入容器为std::vector<int>
,因此迭代器内部类型 ( decltype(*b)
)、展开类型 ( unwrap_t<decltype(*b)>
)、类型类型 ( type
) 和展开类型 ( unwrap_t<type>
) 为 int
,仅reference
是 std::reference_wrapper
.
在外部调用中,输入容器为std::vector<std::reference_wrapper<const int>>
所有类型(除了 reference
)都是 std::reference_wrapper<const int>
,就好像解包器忽略了输入类型。
我在拆包机上做错了什么?我认为这个问题可能与 const
有关传播。
代码可在 Try it online! 上找到。
最佳答案
我认为问题是 *b
返回一个 const 值(因为容器是通过 const 引用传递的)。您的unwrap
仅适用于非常量、非 volatile reference_wrapper
。我会按如下方式解决这个问题:
#include <functional>
namespace detail{
template <typename type_t, class orig_t>
struct unwrap_impl
{
using type = orig_t;
};
template <typename type_t, class V>
struct unwrap_impl<std::reference_wrapper<type_t>,V>
{
using type = type_t;
};
}
template<class T>
struct unwrap {
using type = typename detail::unwrap_impl<std::decay_t<T>, T>::type;
};
template <typename type_t>
using unwrap_t = typename unwrap<type_t>::type;
int main() {
static_assert(std::is_same_v<const int&, unwrap_t<const int &>>);
static_assert(std::is_same_v<const int&, unwrap_t<std::reference_wrapper<const int &>>>);
static_assert(std::is_same_v<const int&, unwrap_t<const std::reference_wrapper<const int &>&>>);
}
这应该返回任何不是 reference_wrapper
的原始类型以及 cv 限定的内部类型 reference_wrapper
及其引用。
说明:我将原件命名为unwrap
来自OP UNWRAP
下面与我的版本进行区分。我们想要调用UNWRAP
的reference_wrapper规范每当std::decay_t<T>
是 std::reference_wrapper
。现在,如果我们始终调用 UNWRAP
,就可以轻松完成此任务。与 std::decay_t<T>
而不是T
。
问题在于,如果 T
不是一个reference_wrapper,这将删除所有资格,即 UNWRAP<std::decay_t<const int>>
是 int
当我们希望它是const int
时。
为了解决这个问题,我们定义了 template<class type_t, class orig_t> struct unwrap_impl
。我们希望始终将第一个参数的衰减类型传递给它,并将原始类型(衰减之前)作为第二个参数传递。然后,我们可以通过一般情况orig_t
作为结果类型(由 using type = orig_t
完成)。
对于规范,我们定义 template<class type_t, class V> struct unwrap_impl<std::reference_wrapper<type_t>, V>
。这将适用于任何时候 type_t
是一个reference_wrapper,即当原始类型是reference_wrapper的某种限定时。我们不关心第二个参数(这将是原始类型),所以我们忽略它。然后我们将reference_wrapper的内部类型作为类型(using type = type_t;
)。
然后我们调用unwrap_impl
基本上定义 template<class type_t> unwrap = detail::unwrap_impl<std::decay_t<type_t>, type_t>;
(这是伪代码,但我认为这更清楚。
一些例子:
unwrap<int> -> unwrap_impl<int, int> -> int
unwrap<const int> -> unwrap_impl<int, const int> -> const int
unwrap<std::reference_wrapper<const int>> -> unwrap_impl<std::reference_wrapper<const int>, std::reference_wrapper<const int>> -> const int
unwrap<const std::reference_wrapper<const int>> -> unwrap_impl<const std::reference_wrapper<const int>, const std::reference_wrapper<const int>> -> const int
(又是更多伪代码,但我希望它清楚)
编辑:修复了一些错误。
编辑2:似乎有效:link
关于c++ - std::reference_wrapper 解开包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59984423/
正在尝试创建一个 python 包。似乎有效,但我收到警告。我的 setup.py 是: #! /usr/bin/env python from distutils.core import setup
我导入了一个数据类型 X ,定义为 data X a = X a 在本地,我定义了一个通用量化的数据类型,Y type Y = forall a. X a 现在我需要定义两个函数, toY 和 fro
我似乎无法让编译器让我包装 Tokio AsyncRead: use std::io::Result; use core::pin::Pin; use core::task::{Context, Po
我有两个函数“a”和“b”。当用户上传文件时,“b”被调用。 “b”重命名文件并返回新文件名。之后应该编辑该文件。像这样: def a(): edits file def b(): r
我使用 Entity Framework 作为我的 ORM,我的每个类都实现了一个接口(interface),该接口(interface)基本上表示表结构(每个字段一个只读属性)。这些接口(inter
有没有办法打开一个程序,通常会打开一个新的jframe,进入一个现有的jframe? 这里是解释,我下载了一个java游戏,其中一个是反射游戏,它在一个jframe中打开,框架内有一堆子面板,我想要做
我想要下面的布局 | AA BBBBBBB | 除非没有足够的空间,在这种情况下 | AA | | BBBBBBB | 在这种情况下,A 是复选框,B 是复选框旁边的 Text
我正在尝试以不同的方式包装我的网站,以便将背景分为 2 部分。灰色部分是主要背景,还有白色部分,它较小并包装主要内容。 基本上我想要this看起来像this . 我不太确定如何添加图像来创建阴影效果,
我正在使用 : 读取整数文件 int len = (int)(new File(file).length()); FileInputStream fis = new FileInputStream(f
我使用 maven 和 OpenJDK 1.8 打包了一个 JavaFX 应用程序我的 pom.xml 中的相关部分: maven-assembly-plugin
我正在使用两个不同的 ItemsControl 来生成一个按钮列表。
我有一个情况,有一个变量会很方便,to , 可以是 TimerOutput或 nothing .我有兴趣提供一个采用与 @timeit 相同参数的宏来自 TimerOutputs(例如 @timeit
我正在尝试包装一个名为 content 的 div与另一个具有不同背景的 div。 但是,当将“margin-top”与 content 一起使用时div,似乎包装 DIV 获得了边距顶部而不是 co
文档不清楚,它似乎允许包装 dll 和 csproj 以在 Asp.Net Core 5 应用程序中使用。它是否允许您在 .Net Core 5 网站中使用针对 .Net Framework 4.6
我被要求开发一个层,该层将充当通用总线,而不直接引用 NServiceBus。到目前为止,由于支持不引人注目的消息,这并不太难。除了现在,我被要求为 IHandleMessages 提供我们自己的定义
我正在尝试包装 getServersideProps使用身份验证处理程序函数,但不断收到此错误:TypeError: getServerSideProps is not a function我的包装看
我有一个项目,它在特定位置(不是/src/resources)包含资源(模板文件)。我希望在运行 package-bin 时将这些资源打包。 我看到了 package-options 和 packag
我正在寻找打印从一系列对象中绘制的 div。我可以通过使用下面的管道语法来实现这一点。 each i, key in faq if (key == 0) |
我在 Meteor.js“main.js - Server”中有这个方法。 Meteor.methods({ messageSent: function (message) { var a
我注意到,如果我的自定义Polymer 1.x元素的宽度比纸张输入元素上的验证错误消息的宽度窄,那么错误将超出自定义元素的右边界。参见下图: 有没有一种机制可以防止溢出,例如在到达自定义元素的边界时自
我是一名优秀的程序员,十分优秀!