即使基类和派生类都有公共(public)数据成员
#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: In function 'int main()': main.cpp:21:10: error: cannot decompose class type 'S': both it and its base class 'M' have non-static data members auto [b,c,d,e] = f();
根据 http://en.cppreference.com/w/cpp/language/structured_binding
案例 3:绑定(bind)到公共(public)数据成员
E 的每个非静态数据成员都必须是 E 的公共(public)直接成员或 E 的相同的明确公共(public)基础,
不明白这是什么意思 E 的相同明确公共(public)基础,
最佳答案
这里有三个形容词,分别规定了三个正交的要求:
- 相同
- 明确
- 公开
按顺序,查看反例可能会有所帮助。在所有情况下,假设 template <class T> T make();
存在。
“相同”的反例:D
有两个成员, 但他们不是 D
的同一基地的成员- i
是 B
的成员但是j
是 D
的成员:
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
“明确”的反例:D
有两个成员, 他们都是 B
的成员, 但它是 D
的不明确基类.
struct B { int i; };
struct M1 : B { };
struct M2 : B { };
struct D : M1, M2 { };
auto [i, j] = make<D>(); // error
如果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
“公共(public)”的反例。这是最简单的一个。如果成员在私有(private)基地中,则无论如何都无法访问他们:
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
另请注意,正如 TC 指出的那样,要求是base 是公开的,而不是成员可访问。也就是说,让成员可以从私有(private)库访问仍然行不通:
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
当然,在所有这些反例案例中,只是因为所有成员都不在 E
的同一个、明确的公共(public)基类中。并不意味着它不能用于结构化绑定(bind)。这只是意味着你必须自己写出绑定(bind):
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
关于c++ - 结构绑定(bind) : binding to public data members (inherited base class ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46003652/