您自己的类型的结构化绑定不是结构或元组(通过 public 成员函数)
Structured bindings for your own type that isn’t a struct or a tuple(via public member function)
我正在浏览 Herb Sutter 的
旅程:走向更强大、更简单的 C++ 编程
为了理解这个概念。最好是写一个我试过但出现错误的程序
Just want to try how to use structure binding on class with private
data .Please ignore the below example.if any example you can provide
#include<iostream>
#include<string>
using namespace std;
class foobar {
public:
foobar() { cout << "foobar::foobar()\n"; }
~foobar() { cout << "foobar::~foobar()\n"; }
foobar( const foobar &rhs )
{ cout << "foobar::foobar( const foobar & )\n"; }
void ival( int nval, string new_string ) { _ival = nval;s=new_string; }
private:
int _ival;
string s;
};
foobar f( int val,string new_string ) {
foobar local;
local.ival( val,new_string );
return local;
}
template<> struct tuple_element<0,foobar> { using type = int; };
template<> struct tuple_element<1,foobar> { using type = string; };
// 2. Now add get<> support (using C++17, because why not; it’s better
// than =delete’ing the primary get<> template and adding specializations)
template<int I>
auto get(const foobar&x) {
if constexpr(I == 0) return x._ival;//'_ival' is a private member of 'foobar'
else if constexpr(I == 1) return x.s;//'s' is a private member of 'foobar'
}
int main(){
foobar ml = f( 1024,"hello" );
auto [ n, s] = f( 1024,"hello" );//Cannot decompose non-public member '_ival' o
return 0;
}
错误
if constexpr(I == 0) return x._ival;//'_ival' is a private member
of 'foobar'
else if constexpr(I == 1) return x.s;//'s' is a private member of 'foobar'
auto [ n, s] = f( 1024,"hello" );//Cannot decompose non-public
需要帮助
1.If 任何人都可以详细说明他实际上在这些方面试图做什么
(请参考提供的link)
// 2. Now add get<> support (using C++17, because why not; it’s better
// than =delete’ing the primary get<> template and adding specializations)
template<int I>
auto get(const S&) {
if constexpr(I == 0) return x.i;
else if constexpr(I == 1) return string_view{x.c}; }
else if constexpr(I == 2) return x.d;
}
2.Any 建议如何修复上述示例的错误
修复 Sutter 示例中的错误
我认为这是 Herb Sutter 博客 typo/glitch 中的一个 post:他应该让那些成员 public,或者为他们提供 getter,或者让 std::get()
函数一个朋友。
此外,Herb 似乎忘记在函数签名中加入 "x"...
get函数的解释
您引用的函数类似于 std::get()
对元组的作用。如果我有
std::tuple<int, std::string> t;
然后
auto x { std::get<0>(t) }; // x is an integer
auto y { std::get<1>(t) }; // y is an std::string
而在 Herb 的例子中,他需要为 S
class 做同样的工作,即 std::get<0>(s)
return [=18= 的第一个成员], std::get<1>(s)
return 第二个成员等。这是必要的,因为否则,您不能使用 S
来初始化结构化绑定。
Hebr 实现中的 "magic" 是他 return 从其函数的不同点获取不同类型的值。这个"magic"是一个if constexpr
的效果。从本质上讲,这意味着编译器会忽略除不相关分支的语法之外的所有内容。所以对于I = 0
,函数是:
auto get(const S&) {
if (true) return x.i;
/* else if constexpr(I == 1) return string_view{x.c};
else if constexpr(I == 2) return x.d;
*/
}
对于 I = 1
它是
template<int I>
auto get(const S&) {
if (false) {/* return x.i; */ ; }
else if (true) return string_view{x.c};
/* else if constexpr(I == 2) return x.d; */
}
}
等然后 auto
选择合适的类型。
这里有很多问题。
首先,为了符合结构化绑定的条件,您需要专门化 tuple_size
:
namespace std {
template <> struct tuple_size<foobar> : std::integral_constant<size_t, 2> { };
}
接下来,您的 tuple_element
专业也必须在 namespace std
:
namespace std {
template <> struct tuple_size<foobar> : std::integral_constant<size_t, 2> { };
template <> struct tuple_element<0,foobar> { using type = int; };
template <> struct tuple_element<1,foobar> { using type = std::string; };
}
接下来,如果您要像往常一样访问私有成员,则必须将 get
声明为 friend
函数:
class foobar {
template <int I> friend auto get(foobar const& );
};
最后,get()
确实有更好的 return 参考,否则你的绑定最终会做出令人惊讶的事情:
template<int I>
auto const& get(const foobar&x) {
if constexpr(I == 0) return x._ival;
else if constexpr(I == 1) return x.s;
}
与其处理 friend
ship,不如让 get()
成为 public 成员,然后编写您需要的三个重载:
class foobar {
public:
template <size_t I>
auto& get() & {
if constexpr (I == 0) return _ival;
else if constexpr (I == 1) return s;
}
template <size_t I>
auto const& get() const& {
if constexpr (I == 0) return _ival;
else if constexpr (I == 1) return s;
}
template <size_t I>
auto&& get() && {
if constexpr (I == 0) return std::move(_ival);
else if constexpr (I == 1) return std::move(s);
}
};
另外 ival()
作为一个函数没有意义。你的构造函数应该只接受参数。
我正在浏览 Herb Sutter 的
旅程:走向更强大、更简单的 C++ 编程
为了理解这个概念。最好是写一个我试过但出现错误的程序
Just want to try how to use structure binding on class with private data .Please ignore the below example.if any example you can provide
#include<iostream>
#include<string>
using namespace std;
class foobar {
public:
foobar() { cout << "foobar::foobar()\n"; }
~foobar() { cout << "foobar::~foobar()\n"; }
foobar( const foobar &rhs )
{ cout << "foobar::foobar( const foobar & )\n"; }
void ival( int nval, string new_string ) { _ival = nval;s=new_string; }
private:
int _ival;
string s;
};
foobar f( int val,string new_string ) {
foobar local;
local.ival( val,new_string );
return local;
}
template<> struct tuple_element<0,foobar> { using type = int; };
template<> struct tuple_element<1,foobar> { using type = string; };
// 2. Now add get<> support (using C++17, because why not; it’s better
// than =delete’ing the primary get<> template and adding specializations)
template<int I>
auto get(const foobar&x) {
if constexpr(I == 0) return x._ival;//'_ival' is a private member of 'foobar'
else if constexpr(I == 1) return x.s;//'s' is a private member of 'foobar'
}
int main(){
foobar ml = f( 1024,"hello" );
auto [ n, s] = f( 1024,"hello" );//Cannot decompose non-public member '_ival' o
return 0;
}
错误
if constexpr(I == 0) return x._ival;//'_ival' is a private member of 'foobar'
else if constexpr(I == 1) return x.s;//'s' is a private member of 'foobar'
auto [ n, s] = f( 1024,"hello" );//Cannot decompose non-public
需要帮助
1.If 任何人都可以详细说明他实际上在这些方面试图做什么 (请参考提供的link)
// 2. Now add get<> support (using C++17, because why not; it’s better
// than =delete’ing the primary get<> template and adding specializations)
template<int I>
auto get(const S&) {
if constexpr(I == 0) return x.i;
else if constexpr(I == 1) return string_view{x.c}; }
else if constexpr(I == 2) return x.d;
}
2.Any 建议如何修复上述示例的错误
修复 Sutter 示例中的错误
我认为这是 Herb Sutter 博客 typo/glitch 中的一个 post:他应该让那些成员 public,或者为他们提供 getter,或者让 std::get()
函数一个朋友。
此外,Herb 似乎忘记在函数签名中加入 "x"...
get函数的解释
您引用的函数类似于 std::get()
对元组的作用。如果我有
std::tuple<int, std::string> t;
然后
auto x { std::get<0>(t) }; // x is an integer
auto y { std::get<1>(t) }; // y is an std::string
而在 Herb 的例子中,他需要为 S
class 做同样的工作,即 std::get<0>(s)
return [=18= 的第一个成员], std::get<1>(s)
return 第二个成员等。这是必要的,因为否则,您不能使用 S
来初始化结构化绑定。
Hebr 实现中的 "magic" 是他 return 从其函数的不同点获取不同类型的值。这个"magic"是一个if constexpr
的效果。从本质上讲,这意味着编译器会忽略除不相关分支的语法之外的所有内容。所以对于I = 0
,函数是:
auto get(const S&) {
if (true) return x.i;
/* else if constexpr(I == 1) return string_view{x.c};
else if constexpr(I == 2) return x.d;
*/
}
对于 I = 1
它是
template<int I>
auto get(const S&) {
if (false) {/* return x.i; */ ; }
else if (true) return string_view{x.c};
/* else if constexpr(I == 2) return x.d; */
}
}
等然后 auto
选择合适的类型。
这里有很多问题。
首先,为了符合结构化绑定的条件,您需要专门化 tuple_size
:
namespace std {
template <> struct tuple_size<foobar> : std::integral_constant<size_t, 2> { };
}
接下来,您的 tuple_element
专业也必须在 namespace std
:
namespace std {
template <> struct tuple_size<foobar> : std::integral_constant<size_t, 2> { };
template <> struct tuple_element<0,foobar> { using type = int; };
template <> struct tuple_element<1,foobar> { using type = std::string; };
}
接下来,如果您要像往常一样访问私有成员,则必须将 get
声明为 friend
函数:
class foobar {
template <int I> friend auto get(foobar const& );
};
最后,get()
确实有更好的 return 参考,否则你的绑定最终会做出令人惊讶的事情:
template<int I>
auto const& get(const foobar&x) {
if constexpr(I == 0) return x._ival;
else if constexpr(I == 1) return x.s;
}
与其处理 friend
ship,不如让 get()
成为 public 成员,然后编写您需要的三个重载:
class foobar {
public:
template <size_t I>
auto& get() & {
if constexpr (I == 0) return _ival;
else if constexpr (I == 1) return s;
}
template <size_t I>
auto const& get() const& {
if constexpr (I == 0) return _ival;
else if constexpr (I == 1) return s;
}
template <size_t I>
auto&& get() && {
if constexpr (I == 0) return std::move(_ival);
else if constexpr (I == 1) return std::move(s);
}
};
另外 ival()
作为一个函数没有意义。你的构造函数应该只接受参数。