- 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/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!