即使基类和派生类都有公共数据成员
#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();
}
Run Code Online (Sandbox Code Playgroud)
得到错误
auto [b,c,d,e] = f();
Run Code Online (Sandbox Code Playgroud)
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的明确公共基础,
无法理解这意味着什么是 同一个明确的E公共基础,
"同一个明确的公共基类"实际上意味着,在整个类层次结构中,只能有一个类中包含成员.
这有点像用于聚合初始化的前C++ 17规则(仅在那里,它们明确禁止继承).C++ 17允许基类聚合初始化,但结构化绑定(概念上是聚合初始化的反转)没有得到备忘录.
这里有三个形容词,它们指定三个正交的要求:
按照顺序,查看反例可能会有所帮助。在所有情况下,都假定template <class T> T make();存在。
“ same”的反例:有两个的成员D,但它们不是-的同一基的成员D- i是的成员B但是j的成员D:
struct B { int i; };
struct D : B { int j; };
auto [i, j] = make<D>(); // error
Run Code Online (Sandbox Code Playgroud)
要解决此问题,要么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
Run Code Online (Sandbox Code Playgroud)
“明确”的反例:有两个成员D,它们都是的成员B,但这是的不明确基类D。
struct B { int i; };
struct M1 : B { };
struct M2 : B { };
struct D : M1, M2 { };
auto [i, j] = make<D>(); // error
Run Code Online (Sandbox Code Playgroud)
如果B是一virtual两个基地M1和M2,那么这将是确定:
struct B { int i; };
struct M1 : virtual B { };
struct M2 : virtual B { };
struct D : M1, M2 { };
auto [i] = make<D>(); // ok
Run Code Online (Sandbox Code Playgroud)
“公共”的反例。这是最简单的。如果成员位于私人基地,则无论如何都无法访问它们:
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
Run Code Online (Sandbox Code Playgroud)
还应注意,正如TC指出的那样,要求的基础是公开的,而不是成员可访问的。也就是说,使成员可以从私有基础访问仍然不起作用:
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
Run Code Online (Sandbox Code Playgroud)
当然,在所有这些反例案例中,仅因为所有成员都不在相同的,明确的公共基类中,E并不意味着它在结构化绑定中不可用。这只是意味着您必须自己写出绑定:
struct B { int i; };
struct D : B { int j; };
namespace std {
template <> struct tuple_size<D> : std::integral_constant<int, 2> { };
template <size_t I> struct tuple_element<I, D> { using type = int; };
}
template <size_t I>
int& get(D& d) {
if constexpr (I == 0) { return d.i; }
else { return d.j; }
}
template <size_t I>
int const& get(D const& d) {
if constexpr (I == 0) { return d.i; }
else { return d.j; }
}
template <size_t I>
int&& get(D&& d) {
if constexpr (I == 0) { return std::move(d).i; }
else { return std::move(d).j; }
}
auto [i,j] = make<D>(); // now ok: we're in case 2 instead of 3
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
537 次 |
| 最近记录: |