1 // { dg-additional-options -std=c++17 }
2 // { dg-do compile }
3 
4 #include <memory>
5 #include <tuple>
6 #include <string>
7 
8 struct X : private std::shared_ptr<int>
9 {
10   std::string fun_payload;
11 };
12 
get(X & x)13 template<int N> std::string& get(X& x)
14 {
15   if constexpr(N==0) return x.fun_payload;
16 }
17 
18 namespace std {
19   template<> class tuple_size<X> : public std::integral_constant<int, 1> {};
20   template<> class tuple_element<0, X> {public: using type = std::string;};
21 }
22 
23 struct X2 : private std::shared_ptr<int>
24 {
25   int fun_payload;
26   template <class T> void get();
27 };
28 
get(X2 & x)29 template<int N> int& get(X2& x)
30 {
31   if constexpr(N==0) return x.fun_payload;
32 }
33 
34 namespace std {
35   template<> class tuple_size<X2> : public std::integral_constant<int, 1> {};
36   template<> class tuple_element<0, X2> {public: using type = int;};
37 }
38 
39 class X3
40 {
41   double fun_payload;
42 public:
get()43   template <int N> double& get()
44   {
45     if constexpr(N==0) return fun_payload;
46   }
47 };
48 
49 namespace std {
50   template<> class tuple_size<X3> : public std::integral_constant<int, 1> {};
51   template<> class tuple_element<0, X3> {public: using type = double;};
52 }
53 
main()54 int main()
55 {
56   X x;
57   auto& [b1] = x;
58   X2 x2;
59   auto& [b2] = x2;
60   X3 x3;
61   auto& [b3] = x3;
62 }
63