Even though both bases class and derived class has public data members
#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();
}
Getting error for
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();
As per http://en.cppreference.com/w/cpp/language/structured_binding
Case 3: binding to public data members
Every non-static data member of E must be a public direct member of E or the same unambiguous public base of E,
Not able to understand what does this mean same unambiguous public base of E,
DEMO
A structural adhesive can be simply described a 'high-strength glue' that bonds together components in a load-bearing structure. Structural adhesives are used extensively in aircraft for bonding metal-to-metal, metal-to-composite and composite-to-composite parts.
Binds the specified names to subobjects or elements of the initializer. Like a reference, a structured binding is an alias to an existing object. Unlike a reference, a structured binding does not have to be of a reference type.
The derived class inherits all members and member functions of a base class. The derived class can have more functionality with respect to the Base class and can easily access the Base class. A Derived class is also called a child class or subclass.
Constructor cannot be inherited but a derived class can call the constructor of the base class.
There are three adjectives here, which specify three orthogonal requirements:
In order, it might help to look at counter-examples. In all cases, assume that template <class T> T make();
exists.
Counter-example for "same": there are two members of D
, but they are not members of the same base of D
- i
is a member of B
but j
is a member of D
:
struct B { int i; };
struct D : B { int j; };
auto [i, j] = make<D>(); // error
To fix this, either j
needs to be a direct member of B
or i
needs to be direct member of 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
Counter-example for "unambiguous": there are two members of D
, they are both members of B
, but it's an ambiguous base class of D
.
struct B { int i; };
struct M1 : B { };
struct M2 : B { };
struct D : M1, M2 { };
auto [i, j] = make<D>(); // error
If B
were a virtual
base of both M1
and M2
, then this would be ok:
struct B { int i; };
struct M1 : virtual B { };
struct M2 : virtual B { };
struct D : M1, M2 { };
auto [i] = make<D>(); // ok
Counter-example for "public". This is the simplest one. If the members are in a private base, they aren't accessible anyway:
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
Note also that, as TC points out, the requirement is that the base be public, not that the members be accessible. That is, making the members accessible from the private base will still not work:
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
Of course, in all of these counterexample cases, just because all the members are not in the same, unambiguous, public base class of E
doesn't mean it's unusuable with structured bindings. It just means that you have to write out the bindings yourself:
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
"same unambiguous public base class" effectively means that, in your entire class hierarchy, there can only be one class that has members in it.
This is sort of like the pre-C++17 rules for aggregate initialization (only there, they explicitly forbid inheritance at all). C++17 allowed base class aggregate initialization, but structured binding (which is conceptually the inverse of aggregate initialization) didn't get the memo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With