结构绑定:绑定到公共数据成员(继承的基类)

时间:2017-09-01 15:35:09

标签: c++ c++17

即使基类和派生类都有公共数据成员

#include <iostream>
class M {
    public:
    int x = 2;
    volatile double y=3;
};

class S:public M {
    public:
    int x1 = 4 ;
    volatile double y1 = 5;

};

int main() {
    S f();
    S a;
    std::cout<<a.x<<a.y<<a.x1<<a.y1;
    auto [b,c,d,e] = f(); 
}

获取错误

 auto [b,c,d,e] = f(); 
  

main.cpp:在函数'int main()'中:main.cpp:21:10:错误:不能   分解类类型'S':它和它的基类'M'都有   非静态数据成员        auto [b,c,d,e] = f();

根据http://en.cppreference.com/w/cpp/language/structured_binding

案例3:绑定到公共数据成员

E的每个非静态数据成员必须是E的公共直接成员或 的明确公共基础,

无法理解这是什么意思 同样明确的E 公共基础,

DEMO

2 个答案:

答案 0 :(得分:6)

&#34;同样明确的公共基础&#34;有效地意味着,在整个类层次结构中,只能有一个类,其中包含成员。

这有点像聚合初始化的前C ++ 17规则(仅在那里,它们明确禁止继承)。 C ++ 17允许基类聚合初始化,但结构化绑定(概念上是聚合初始化的反转)并没有得到备忘录。

答案 1 :(得分:4)

这里有三个形容词,它们指定了三个正交要求:

  1. 相同
  2. 明确的
  3. 公共
  4. 为了查看反例,可能会有所帮助。在所有情况下,假设template <class T> T make();存在。

    &#34;相同&#34;的反例:D有两名成员,但他们不是D的同一基数的成员 - iB的成员,但jD的成员:

    struct B { int i; };
    struct D : B { int j; };
    
    auto [i, j] = make<D>(); // error
    

    要解决此问题,j需要成为B的直接成员或i需要成为D的直接成员:

    struct B { int i, j; };
    struct D : B { };
    auto [i, j] = make<D>(); // ok
    
    struct B { };
    struct D : B { int i, j; };
    auto [i, j] = make<D>(); // ok
    

    &#34;明确&#34;的反例:D有两个成员,他们都是B的成员,但它是D的模糊基类{1}}。

    struct B { int i; };
    struct M1 : B { };
    struct M2 : B { };
    struct D : M1, M2 { };
    
    auto [i, j] = make<D>(); // error
    

    如果B是[{1}}和virtual的{​​{1}}基数,那么这样就可以了:

    M1

    &#34; public&#34;的反例。这是最简单的一个。如果成员在私人基地,他们无论如何都无法访问:

    M2

    另请注意,正如TC指出的那样,要求是 base 是公开的,而不是成员可访问。也就是说,从私人基地访问成员仍然无效:

    struct B { int i; };
    struct M1 : virtual B { };
    struct M2 : virtual B { };
    struct D : M1, M2 { };
    
    auto [i] = make<D>(); // ok
    

    当然,在所有这些反例中,仅仅因为所有成员都不在同一个,明确的公共基类struct B { int i; }; struct D : private B { }; make<D>().i; // error, as-is auto [i] = make<D>(); // error, non-public base, but really same reason 并不意味着它对结构化绑定不可用。它只是意味着你必须自己写出绑定:

    struct B { int i; };
    struct D : private B { using B::i; };
    
    make<D>().i;        // ok now, due to the using-declaration
    auto [i] = make<D>(); // still error, B is still private base