标签: structured-bindings

为什么GCC会为结构化绑定诊断一个未使用的变量,而Clang却没有?

让我们从一个最小的例子开始:

#include <utility>

int main()
{
    auto [a, b] = std::pair(1, 'A');
    return a;
}
Run Code Online (Sandbox Code Playgroud)

与GCC 7.3编译通过-std=c++17,并-Wunused-variable,并运行它:

<source>: In function 'int main()':
<source>:5:15: warning: unused variable 'b' [-Wunused-variable]
     auto [a, b] = std::pair(1, 'A');
               ^
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会可能正确报告缺席使用b,但错误地将其称为变量.引用[dcl.struct.bind]/1:

结构化绑定声明将标识符列表标识符 v0,v1,v2,... 引入为结构化绑定的名称([basic.scope.declarative]).

所以b显然不是变量,而是名称.使用Clang 6.0.0编译相同的代码,并使用相同的标志,我们不会得到任何警告.return a;从代码中删除语句:

#include <utility>

int main()
{
    auto [a, b] = std::pair(1, 'A');
    // return a;
}
Run Code Online (Sandbox Code Playgroud)

并使用Clang再次编译它,我们得到:

<source>:5:10: warning: unused variable …
Run Code Online (Sandbox Code Playgroud)

c++ gcc language-lawyer c++17 structured-bindings

6
推荐指数
1
解决办法
554
查看次数

结构化绑定是否可重用?

我正在使用Windows 10,Visual Studio 2017 v15.7.1 /std:c++latest /permissive-

这个带结构化绑定的简单代码将无法编译:

auto [a, b] = func1(x, y, z); // auto func1() -> std::tuple<double, double, double>
[a, b] = func2(x, y, z); // same signature as func2
Run Code Online (Sandbox Code Playgroud)

E1277 attributes are not allowed here.

下面的代码也不会编译,同样的错误

double a, b;
[a, b] = func1(x, y, z);
[a, b] = func2(x, y, z);
Run Code Online (Sandbox Code Playgroud)

auto [a, b] = func1(x, y, z);
auto [a, b] = func2(x, y, z);
Run Code Online (Sandbox Code Playgroud)

也不会编译,理所当然地抱怨重新定义.

它编译的唯一方法是

auto [a1, b1] = func1(x, y, …
Run Code Online (Sandbox Code Playgroud)

c++ visual-c++ language-lawyer c++17 structured-bindings

6
推荐指数
1
解决办法
357
查看次数

结构化绑定违规

代码如下

#include <tuple>
 
int main() 
{
    auto [a] = std::make_tuple(1);
    return [a]() -> int { return a; }();
}
Run Code Online (Sandbox Code Playgroud)

在 clang 12 中产生错误:

<source>:6:13: error: 'a' in capture list does not name a variable
    return [a]() -> int { return a; }();
<source>:6:34: error: reference to local binding 'a' declared in enclosing function 'main'
    return [a]() -> int { return a; }();
Run Code Online (Sandbox Code Playgroud)

然而,Visual Studio 2019 和 gcc 11 都-std=c++20 -Wall -Wextra -pedantic-errors接受它。https://gcc.godbolt.org/z/jbjsnfWfj

所以它们仍然违反了结构化绑定永远不是变量名称的规则,使它们永远无法捕获?

c++ stdtuple structured-bindings c++20

6
推荐指数
1
解决办法
150
查看次数

decltype 不保留结构化绑定中的 ref 限定符

通常 decltype 保留 ref 限定符

auto a = 0;
auto& a_ref = a;
static_assert(std::is_reference_v<decltype(a_ref)>);
Run Code Online (Sandbox Code Playgroud)

但当它的参数是从结构化绑定获得时显然不是

auto a = 0;
auto& a_ref = a;
static_assert(std::is_reference_v<decltype(a_ref)>);
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/qWT574fr9

我很确定,i并且d是这里的参考。它们应该是根据旧的新事物,智能感知是这样告诉我的。

c++ decltype type-traits structured-bindings

6
推荐指数
1
解决办法
103
查看次数

解压为函数参数

理论上是否可以添加语言功能以将结构解压到函数实际参数列表中?我的意思是以下内容。

template< typename ...Ts >
void f(Ts... values) { (std::cout << ... << values) << std::endl; }

struct S { int a; char c; double d; };
S s{1, '2', 3.0};
f([s]);

void g(int, int, int) {}

g([s]); // warning about narrowing conversion

void h(int &, int &, int &) {}

h([s]); // hard error ("cannot bind to...")
Run Code Online (Sandbox Code Playgroud)

处理成员数量未知的合适结构会很方便。因为由于缺乏模板上下文,当前的结构化绑定无法“解压”未知数量的组件(例如 )的结构,而模板上下文只能处理可变数量的类型/值。auto... [x] = s;operator ...

这种方式有什么缺点?

c++ language-lawyer c++17 structured-bindings

5
推荐指数
0
解决办法
940
查看次数

与现有变量的结构化绑定不可能?

是否可以使用现有的变量作为与之相关的返回值的目标structured bindings

auto f()
{
    return std::make_tuple(1,2.2);
}

int main()
{
    int x;
    double z;

    [ x, z ] = f();  // Did not work in gcc 7.1

    // structured bindings only work with "new" vars?
    auto [a, b] = f();  // works fine
}
Run Code Online (Sandbox Code Playgroud)

c++ c++17 structured-bindings

5
推荐指数
1
解决办法
330
查看次数

为什么clang ++会报告一个结构化绑定,其中"在初始化期间存储到'...'的值永远不会被读取"?

我有以下测试用例:

testcase("[room] exits") {
    auto [center, east, north, south, west] = make_test_rooms();

    check_eq(center->east(), east);
    check_eq(center->north(), north);
    check_eq(center->south(), south);
    check_eq(center->west(), west + 1);
}
Run Code Online (Sandbox Code Playgroud)

当我编译它时,clang ++(clang版本5.0.1(标签/ RELEASE_501/final))报告:

room.cpp:52:7: note: Value stored to '[center, east, north, south, west]' during its initialization is never read
Run Code Online (Sandbox Code Playgroud)

在上面的代码,testcasecheck_eq用于定义的宏的文档测试单元测试包展开后DOCTEST_TEST_CASE()(某种自注册变量+函数对)和DOCTEST_CHECK_EQ(基本上,"断言== B"魔术带处理).

我知道这段代码正在执行,因为这west + 1是故意引入的错误.当我运行我的测试时,我得到一个像这样的失败消息:

===============================================================================
/.../room.cpp(51)
TEST CASE:  [room] exits

/.../room.cpp(57) ERROR!
  CHECK_EQ( center->west(), west + 1 )
with expansion:
  CHECK_EQ( 0x00007fd6f1d011a0, 0x00007fd6f1d011f8 )
Run Code Online (Sandbox Code Playgroud)

据我所见,我使用结构化绑定中的所有值: …

c++ clang++ c++17 structured-bindings

5
推荐指数
1
解决办法
449
查看次数

您是否可以在类类型上使用结构化绑定来违反ODR

结构化绑定功能表示,如果tuple_size模板是完整类型,它会像分解一样使用元组.如果std::tuple_size在程序中的某一点是给定类型的完整类型并且在另一点未完成,会发生什么?

#include <iostream>
#include <tuple>

using std::cout;
using std::endl;

class Something {
public:
    template <std::size_t Index>
    auto get() {
        cout << "Using member get" << endl;
        return std::get<Index>(this->a);
    }

    std::tuple<int> a{1};
};

namespace {
    auto something = Something{};
}

void foo() {
    auto& [one] = something;
    std::get<0>(one)++;
    cout << std::get<0>(one) << endl;
}

namespace std {
template <>
class tuple_size<Something> : public std::integral_constant<std::size_t, 1> {};
template <>
class tuple_element<0, Something> {
public:
    using type = int; …
Run Code Online (Sandbox Code Playgroud)

c++ one-definition-rule undefined-behavior c++17 structured-bindings

5
推荐指数
1
解决办法
174
查看次数

未知自定义结构上的结构化绑定

简洁版本:

我希望能够将结构转换为元组。至少是类型。在下面的代码中,convertToTuple函数不起作用,因为可变参数不能在结构化绑定中使用(据我所知)。关键行是:auto& [values...] = value;

struct Vec3 {
 float x;
 float y;
 float z;
};
template <typename T>
auto structToTuple(T &value) {
 auto& [values...] = value;  //doesn't work
 return std::make_tuple<decltype(values)...>(values...);
}
Vec3 v;
std::tuple<float, float, float> t = structToTuple(v);
Run Code Online (Sandbox Code Playgroud)

基本上,我需要的是一种将自定义结构的类型转换为元组的方法,其中包含结构中的所有类型。例如:

struct Ray {Vec3, Vec3} -> std::tuple<
 std::tuple<float, float, float>,
 std::tuple<float, float, float>>;
Run Code Online (Sandbox Code Playgroud)

详细问题:

我想创建一个模板化函数,它将一个类型或类型列表作为模板参数并生成一个纹理列表,每个纹理包含一个项目。其他函数可以对纹理列表进行采样,并将这些值打包在一起以返回相同的类型。例如,如果我有一个类型:

std::pair<std::tuple<int, int>, int> value;
std::tuple<Texture<int, int>, Texture<int>> tex = createTexture(value);
std::pair<std::tuple<int, int>, int> thisshouldwork = sample(tex);
Run Code Online (Sandbox Code Playgroud)

上面的代码只是我想要做的一个简单示例,而不是我的实际代码。在这种情况下,将创建 2 个纹理,一个纹理将包含元组中的两个 int,另一个纹理将包含单个 int 类型。我的目的是将纹理处理隐藏在接口后面,我可以在纹理中存储任意值(只要它由一些简单类型组成),然后将其上传到 GPU …

c++ variadic-templates c++17 structured-bindings

5
推荐指数
1
解决办法
1528
查看次数

类模板内部类的类似元组的结构化绑定

我想为类模板的内部类提供结构化绑定。我怎样才能专门研究std::tuple_size这个内部类?

我无法对数据成员使用结构化绑定,因为内部类可能是与该功能不兼容的类型。所以我需要提供类似元组的结构化绑定。为了向内部类提供这样的功能,我需要部分专注std::tuple_sizenamespace std. 问题是我得到了参数(外部类)的非推导上下文。T

我知道我可以将内部类放在全局命名空间中,从而解决每个问题,但是有什么方法可以得到相同的结果,保持类内部?

#include <tuple>

template<typename T>
class Collection
{
    public:
        struct Element
        {
            int id;
            T actual_element;
        };

    //...
};


namespace std 
{
    template<typename T>
    struct tuple_size<typename Collection<T>::Element> // Error! Non-deduced context
        : std::integral_constant<std::size_t, 2> {};
}



//Collection iterators...

int main()
{
    Collection<int> collection;

    for (auto & [id, element] : collection) //what I'd like to achieve
        //do some stuff...
}
Run Code Online (Sandbox Code Playgroud)

c++ templates inner-classes c++17 structured-bindings

5
推荐指数
1
解决办法
375
查看次数