我在这里找到了*C++结构化绑定的原始提议.它提出了一种轻松绑定多个返回值的方法,即:
auto {a, b} = minmax(data);
Run Code Online (Sandbox Code Playgroud)
但现在我看到每个人都指向C++ 17/C++ 1z提议语法
auto [a, b] = minmax(data);
Run Code Online (Sandbox Code Playgroud)
既然我已经学会了"列表被编写{like,this}",那么会出现一个新的列表语法?为什么?花括号有什么问题?
考虑以下片段来测试即将发布的C++ 17特性分解声明(以前称为结构化绑定)
#include <cassert>
#include <utility>
constexpr auto divmod(int n, int d)
{
return std::make_pair(n / d, n % d); // in g++7, also just std::pair{n/d, n%d}
}
int main()
{
constexpr auto [q, r] = divmod(10, 3);
static_assert(q == 3 && r ==1);
}
Run Code Online (Sandbox Code Playgroud)
这在g ++ 7-SVN和clang-4.0-SVN上都失败了,并带有以下消息:
分解声明不能声明'constexpr'
删除constexpr定义并更改为assert()两个编译器上的常规工作.
关于此功能的WG21论文constexpr均未提及关键字,无论是正面还是负面.
问题:为什么不允许分解声明constexpr?(除了"因为标准这么说").
具有模式匹配的函数式语言(有时?)有可能忽略一些绑定值,但是使用C++ 17结构化绑定似乎没有办法(std :: ignore with structured bindings?).建议是使用虚拟名称,但随后我们会收到有关未使用变量的警告.
有了clang和gcc的最新元首,这就做了预期的事情,这很好用,
[[maybe_unused]] auto x =4 ; // fine, no warning
[[maybe_unused]] auto [a,dummyb,dummyc] = std::tuple<int,int,float>(1,1,1.0f);
Run Code Online (Sandbox Code Playgroud)
但我也希望这会奏效:
auto [g,[[maybe_unused]]dummyh,[[maybe_unused]]dymmyi] =
std::tuple<int,int,float>(1,1,1.0f);
Run Code Online (Sandbox Code Playgroud)
是否有一个特定的原因属性不能在这里使用?(在标准和技术上).gcc或clang都不接受这个.
编辑,收集支持状态:(感谢godbolt /编译器浏览器).它按预期工作(也可能更早):
MSVC 17.3.5(和Visual Studio GUI)允许该属性,但它不适用于结构化绑定.错误报告
使用以下代码,我得到一个编译错误C2065 'a': undeclared identifier(使用Visual Studio 2017):
[] {
auto [a, b] = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }(); //error C2065
}();
Run Code Online (Sandbox Code Playgroud)
但是,以下代码编译:
[] {
int a, b;
std::tie(a, b) = [] {return std::make_tuple(1, 2); }();
auto r = [&] {return a; }();
}();
Run Code Online (Sandbox Code Playgroud)
我以为这两个样本是等价的.它是编译器错误还是我错过了什么?
书写是否const auto& [a, b] = f();延长从返回的对象的终身保障f(),或者至少对象a和b必然?通过阅读提案,我没有看到任何明显的语言,以确保它确实存在,除非它只是被其他东西覆盖.但是,以下内容并未延长临时的生命周期,因此我不知道它将如何覆盖:
const auto& a = std::get<0>(f());
Run Code Online (Sandbox Code Playgroud)
在论文的顶部,似乎表明它已被覆盖
分解声明的cv-qualifiers和ref-qualifier应用于为初始化程序引入的引用,而不是单个成员别名
但是在实际标准的拟议措辞中,我看到的最接近的提法如下,但我不知道如何阅读它以获得我正在寻找的保证:
如果e是未分类的id-expression,命名从分解声明的identifier-list引入的左值或引用,则decltype(e)是分解声明规范中给出的引用类型
似乎gcc和clang都延长了返回对象的生命周期,直到基于wandbox实验的范围结束.一个实现我自己类型的所有铃声和口哨声的丑陋似乎延长了外部对象及其他数据成员的生命周期.
虽然几乎可以肯定作者的意图,但我想确切地知道这种语言可以保证这是安全的.
考虑一个例子:
#include <iostream>
#include <type_traits>
#include <tuple>
int main() {
auto tup = std::make_tuple(1, 2);
auto [ a, b ] = tup;
decltype(auto) e = a;
std::cout << std::boolalpha << std::is_reference_v<decltype(e)> << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在这个简单的例子中,clang(输出:)false和gcc(输出:)true不一致.记住,例如这个Q&As应该e是一个参考还是一个gcc bug?或者代码可能不正确?
假设我有一个类型的对象
std::map<std::string, std::tuple<int, float>> data;
Run Code Online (Sandbox Code Playgroud)
是否可以以嵌套的方式访问元素类型(例如,当在ranged for循环中使用时)
for (auto [str, [my_int, my_float]] : data) /* do something */
Run Code Online (Sandbox Code Playgroud) 考虑这段代码(演示):
#include <tuple>
#include <type_traits>
struct Ag{int i;int j;};
using T = std::tuple<int,int>;
using Ar = int[2];
const Ag ag {};
const T t {};
const Ar ar {};
void bind_ag(){
auto [i,j] = ag;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_t(){
auto [i,j] = t;
static_assert(std::is_same_v<decltype((i)),int&>);
}
void bind_ar(){
auto [i,j] = ar;
static_assert(std::is_same_v<decltype((i)),int&>); //For GCC
static_assert(std::is_same_v<decltype((i)),const int&>); //For Clang (and standard?)
}
Run Code Online (Sandbox Code Playgroud)
甲结构化结合到一个副本const的c-阵列被声明常量由锵和非const由GCC.
GCC对c阵列的行为与聚合或类似元组类型的行为一致.
另一方面,从我对标准的阅读中,我认为Clang遵循所写的内容.在[dcl.struct.bind]/1中, e具有类型cv A,其中A是初始化表达式的类型,cv是结构化绑定声明的cv限定符.并且初始化表达式的类型 …
是否可以使用带向量的结构化绑定?
例如
std::vector<int> vec{1, 2, 3};
auto [a, b, c] = vec;
Run Code Online (Sandbox Code Playgroud)
不幸的是,上面的代码不起作用(在GCC下),但也许有一种不同的方式(结构化绑定)允许将向量的前三个值分配给三个变量.
考虑:
struct Point { int x, y; };
int main()
{
const auto [x, y] = Point{};
}
Run Code Online (Sandbox Code Playgroud)
这段代码在C++ 17模式下用gcc 7.1编译得很好,但是这个:
#include <utility>
struct Point { int x, y; };
int main()
{
const auto [x, y] = Point{};
}
Run Code Online (Sandbox Code Playgroud)
给出错误:
bug.cpp: In function 'int main()':
bug.cpp:7:16: error: 'std::tuple_size<const Point>::value' is not an integral constant expression
const auto [x, y] = Point{};
^~~~~~
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?一个编译器错误,或者这是结构化绑定应该如何工作?