在std :: unordered_map上运行基于范围的for循环时,似乎循环变量的类型不使用引用类型:
std::unordered_map<int, int> map = { {0, 1}, {1, 2}, {2, 3} };
for(auto&[l, r] : map)
static_assert(std::is_same_v<decltype(r), int&>);
Run Code Online (Sandbox Code Playgroud)
MSVC 2017,gcc 8.2和clang 7.0.0都报告了一个失败的断言.将此反对到std :: vector,其中断言不会失败,正如人们所期望的那样:
std::vector<int> vec = { 1, 2, 3 };
for(auto& r : vec)
static_assert(std::is_same_v<decltype(r), int&>);
Run Code Online (Sandbox Code Playgroud)
然而,在MSVC 2017和gcc 8.2上,修改局部变量r的循环将具有可观察到的副作用:
#include <iostream>
#include <type_traits>
#include <unordered_map>
#include <vector>
int main() {
std::unordered_map<int, int> a = { {0, 1}, {1, 2}, {2, 3} };
for(auto[l, r] : a)
std::cout << l << "; " << …Run Code Online (Sandbox Code Playgroud) 的最新草稿结构化绑定提案(在其上的C++ 17特征是基于)的要求std::tuple_size,构件get或std::get,和std::tuple_element.以前的草稿只需要std::tuple_size和成员get或std::get.据我所知,没有讨论增加这一点,它只是出现在最终草案中.是否有令人信服的理由要求tuple_element专业化,考虑到我认为它可以作为一般实施
template<std::size_t index, typename T>
struct tuple_element {
using type = decltype(std::get<index>(std::declval<T>()));
};
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么要添加此要求?
struct X { int a, b; };
int main()
{
auto p = std::pair{ 1, 2 };
const auto&[r1, r2] = p; // ok
X x{ 1, 2 };
const auto&[r3, r4] = x; // error
}
Run Code Online (Sandbox Code Playgroud)
clang 7.0(在Windows上)的错误信息:
error : cannot decompose this type; 'std::tuple_size<const X>::value' is not a valid
integral constant expression
Run Code Online (Sandbox Code Playgroud)
为什么结构化绑定在struct上不能按预期工作?
我有以下代码:
#include "stdafx.h"
#include <unordered_map>
#include <cassert>
int main()
{
struct Foo { int a; };
std::unordered_map<int, Foo> foos{ { 0, { 3 } }, { 1, { 4 } } };
for (auto &[i, foo] : foos)
{
foo.a = 6; //doesn't change foos[i].a
assert(&foo.a == &foos[i].a); //does not pass
}
auto &[i, foo] = *foos.begin();
foo.a = 7; //changes foo[0].a
assert(&foo.a == &foos[0].a); //passes
}
Run Code Online (Sandbox Code Playgroud)
我的问题:
为什么第一个断言语句在第二个传递时没有通过?为什么我不能改变的价值foo在foos地图中基于范围循环?
编译: MSVS ++ 17 Visual studio 15.3.2 …
根据这个答案,显然没有充分的理由说明为什么不允许结构化绑定是constexpr,但标准仍然禁止它.但是,在这种情况下,是否应该禁止在constexpr函数中使用结构化绑定?考虑一个简单的片段:
#include <utility>
constexpr int foo(std::pair<int, int> p) {
auto [a, b] = p;
return a;
}
int main() {
constexpr int a = foo({1, 2});
static_assert(a == 1);
}
Run Code Online (Sandbox Code Playgroud)
请考虑以下使用C++ 17结构化绑定的代码:
int a = 0, b = 0;
auto [x, y] = std::tie(a, b);
y = 1;
std::cout << a << ' ' << b << '\n';
Run Code Online (Sandbox Code Playgroud)
由于我使用auto,我希望的代码打印0 0的y应该是一个拷贝.然而,它打印0 1.为什么?我认为裸露auto从不推断参考.
以下代码应该编译吗?
#include <type_traits>
void foo() {
const std::pair<int, int> x = {1, 2};
auto [a, b] = x;
static_assert(std::is_const_v<decltype(a)>);
static_assert(std::is_const_v<decltype(b)>);
}
Run Code Online (Sandbox Code Playgroud)
那么,这是MSVC错误吗?
该标准是不是直接在这里(我有一个快速浏览一下),但考虑规则auto,我想,a并且b应该被复制丢弃CV-预选赛。
我想使用结构绑定遍历地图,忽略键:
for (auto& [unused, val] : my_map)
do_something(val);
Run Code Online (Sandbox Code Playgroud)
我尝试过gcc-7.2.0的不同选项:
// The warning is issued
for ([[maybe_unused]] auto& [unused, val] : my_map)
do_something(val);
// Syntax error
for (auto& [[[maybe_unused]] unused, val] : my_map)
do_something(val);
// The same two combinations above with [[gnu::unused]].
Run Code Online (Sandbox Code Playgroud)
似乎该[[maybe_unused]]属性尚未实现结构绑定.
这有什么简单的解决方案吗?任何宏,gcc/gnu扩展名,或任何暂时禁止该特定警告的pragma对我来说都没有问题; 例如,在我使用基于范围的for的整个函数体中禁用它,因为我使用它的函数非常短(它基本上是两个不同映射的两个范围,具有精确的行为).
我用来编译项目的(相关)选项是:
-std=c++17 -Wall -Wextra -Werror -pedantic -pedantic-errors
Run Code Online (Sandbox Code Playgroud)
我目前要做的是,但这很难看:
for (auto& [unused, val] : my_map)
(void)unused, do_something(val);
Run Code Online (Sandbox Code Playgroud) 鉴于这些声明:
int a[3] {10,20,30};
std::tuple<int,int,int> b {11,22,33};
Run Code Online (Sandbox Code Playgroud)
我可以使用结构化绑定声明来解码a和b:
auto [x1,y1,z1] = a;
auto [x2,y2,z2] = b;
Run Code Online (Sandbox Code Playgroud)
但是,如果x1,y1等已经存在了,我该怎么办?
std::tie(x1,y1,z1) = a; // ERROR
std::tie(x2,y2,z2) = b; // OK
Run Code Online (Sandbox Code Playgroud)
这适用b但不适用a.是否有一个类似的简单构造,对工作a,还是我去取a[0],a[1]并a[2]分别?
为什么在这种情况下我不能使用 C++17 结构化绑定?
std::map<int, int> m;
std::find_if( m.cbegin(), m.cend(), []( const auto & [x, y] ){ return x == y; } );
Run Code Online (Sandbox Code Playgroud)