Har*_*ngh 7 c++ stdtuple c++17 structured-bindings if-constexpr
我正在经历Herb Scutter的
旅程:走向更强大,更简单的C++编程
结构绑定部分
为了理解这个概念.Best是编写一个我试过的程序,但是遇到了一些错误
只是想尝试如何在类上使用私有数据的结构绑定.请忽略下面的示例.如果您能提供任何示例
#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;
}
Run Code Online (Sandbox Code Playgroud)
错误
如果constexpr(I == 0)返回x._ival; //'_ ival'是'foobar'的私有成员
否则,如果constexpr(I == 1)返回xs; //'s'是'foobar'的私有成员
auto [n,s] = f(1024,"hello"); //无法分解非公开
需要帮助
1.如果有人能详细说明他在这些方面的实际尝试(请参阅提供的链接)
// 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;
}
Run Code Online (Sandbox Code Playgroud)
2.任何建议如何修复上述示例的错误
这里有很多问题。
首先,为了有资格使用结构化绑定,您需要专门研究tuple_size:
namespace std {
template <> struct tuple_size<foobar> : std::integral_constant<size_t, 2> { };
}
Run Code Online (Sandbox Code Playgroud)
接下来,您的专长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; };
}
Run Code Online (Sandbox Code Playgroud)
接下来,如果您要照常访问私有成员,则get必须将您声明为一个friend函数:
class foobar {
template <int I> friend auto get(foobar const& );
};
Run Code Online (Sandbox Code Playgroud)
最后,get()确实有更好的返回引用,否则您的绑定最终将完成令人惊讶的事情:
template<int I>
auto const& get(const foobar&x) {
if constexpr(I == 0) return x._ival;
else if constexpr(I == 1) return x.s;
}
Run Code Online (Sandbox Code Playgroud)
而不是与friend船舶打交道,只需要成为get()一个公共成员,然后编写所需的三个重载就容易了:
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);
}
};
Run Code Online (Sandbox Code Playgroud)
同样ival()作为一个函数没有任何意义。您的构造函数应该只接受参数。
我认为这是赫伯·萨特(Herb Sutter)博客文章中的一个拼写错误/小故障:他应该将这些成员公开,或者为他们提供吸气剂,或者使该std::get()函数成为朋友。
另外,赫伯似乎忘记在函数签名中添加“x”......
std::get()您引用的函数与元组的工作原理类似。如果我有
std::tuple<int, std::string> t;
Run Code Online (Sandbox Code Playgroud)
然后
auto x { std::get<0>(t) }; // x is an integer
auto y { std::get<1>(t) }; // y is an std::string
Run Code Online (Sandbox Code Playgroud)
在 Herb 的示例中,他需要对类进行相同的工作S,即std::get<0>(s)返回 的第一个成员s,std::get<1>(s)返回第二个成员等。这是必要的,因为否则,您不能用于S初始化结构化绑定。
Hebr 实现的“魔力”在于他从函数中的不同点返回不同类型的值。这种“魔力”就是 的效果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;
*/
}
Run Code Online (Sandbox Code Playgroud)
因为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; */
}
}
Run Code Online (Sandbox Code Playgroud)
等等,然后auto选择合适的类型。
| 归档时间: |
|
| 查看次数: |
1553 次 |
| 最近记录: |