如何迭代元组(使用C++ 11)?我尝试了以下方法:
for(int i=0; i<std::tuple_size<T...>::value; ++i)
std::get<i>(my_tuple).do_sth();
Run Code Online (Sandbox Code Playgroud)
但这不起作用:
错误1:抱歉,未实现:无法将"Listener ..."扩展为固定长度的参数列表.
错误2:我不能出现在常量表达式中.
那么,我如何正确迭代元组的元素?
a std::pair和std::tuple只有两个成员之间有区别吗?(除了明显std::pair需要两个,只有两个成员,tuple可能会少...)
有一条规则说明std :: tuple的成员被破坏了吗?
例如,如果Function1返回一个std::tuple<std::unique_ptr<ClassA>, std::unique_ptr<ClassB>>to Function2,那么我可以确定(当Function2剩下的范围时)ClassB第二个成员ClassA引用的实例在第一个成员引用的实例之前被销毁吗?
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > Function1()
{
std::tuple< std::unique_ptr< ClassA >, std::unique_ptr< ClassB > > garbage;
get<0>(garbage).reset( /* ... */ );
get<1>(garbage).reset( /* ... */ );
return garbage;
}
void Function2()
{
auto to_be_destroyed = Function1();
// ... do something else
// to_be_destroyed leaves scope
// Is the instance of ClassB destroyed before the instance of ClassA?
}
Run Code Online (Sandbox Code Playgroud) 令我惊讶的是,我遇到了另一个障碍,例如C++20 行为用相等运算符破坏了现有代码?.
考虑一个简单的不区分大小写的键类型,用于例如std::setor std::map:
// Represents case insensitive keys
struct CiKey : std::string {
using std::string::string;
using std::string::operator=;
bool operator<(CiKey const& other) const {
return boost::ilexicographical_compare(*this, other);
}
};
Run Code Online (Sandbox Code Playgroud)
简单的测试:
using KeySet = std::set<CiKey>;
using Mapping = std::pair<CiKey, int>; // Same with std::tuple
using Mappings = std::set<Mapping>;
int main()
{
KeySet keys { "one", "two", "ONE", "three" };
Mappings mappings {
{ "one", 1 }, { "two", 2 }, { "ONE", 1 }, { "three", …Run Code Online (Sandbox Code Playgroud) 这是测试代码.
元组测试:
using namespace std;
int main(){
vector<tuple<int,int>> v;
for (int var = 0; var < 100000000; ++var) {
v.push_back(make_tuple(var, var));
}
}
Run Code Online (Sandbox Code Playgroud)
配对测试:
#include <vector>
using namespace std;
int main(){
vector<pair<int,int>> v;
for (int var = 0; var < 100000000; ++var) {
v.push_back(make_pair(var, var));
}
}
Run Code Online (Sandbox Code Playgroud)
我通过Linux time命令进行了时间测量.结果是:
| | -O0 | -O2 |
|:------|:-------:|:--------:|
| Pair | 8.9 s | 1.60 s |
| Tuple | 19.8 s | 1.96 s |
Run Code Online (Sandbox Code Playgroud)
我想知道,为什么O0中的这两个数据结构之间存在如此大的差异,因为它们应该非常相似.02中只有一点不同.
为什么O0的差异如此之大,为什么会有任何差异呢?
编辑:
v.resize()的代码
对:
#include …Run Code Online (Sandbox Code Playgroud) 在实现自定义tuple(此处)时,我发现有一个swap()带有const参数的有线函数(cppreference):
template< class... Types >
constexpr void swap( const std::tuple<Types...>& lhs,
const std::tuple<Types...>& rhs ) noexcept(/* see below */);
Run Code Online (Sandbox Code Playgroud)
和一个 const 限定的swap()成员函数 ( cppreference ):
constexpr void swap( const tuple& other ) noexcept(/* see below */) const;
Run Code Online (Sandbox Code Playgroud)
const意味着该对象是只读的,但是要交换两个对象,它必须修改对象,这违反了性质const。
那么,const swap() 函数的目的是什么?
让我说我有
std::tuple<T0, T1, T2> my_tuple{x0, x1, x2};
Run Code Online (Sandbox Code Playgroud)
其中T0,T1和T2是值类型(即没有混叠是可能的).
只要每个线程访问不同的元素,访问my_tuple元素并从多个线程同时改变它们是否安全std::get?
例:
template <typename T>
void process(T& x) { /* mutate `x` */ }
// ...
std::thread{[&]{ process(std::get<0>(my_tuple)); }}.detach();
std::thread{[&]{ process(std::get<1>(my_tuple)); }}.detach();
std::thread{[&]{ process(std::get<2>(my_tuple)); }}.detach();
Run Code Online (Sandbox Code Playgroud)
本能地,我会说它是安全的,my_tuple可以被认为是struct { T0 x0; T1 x1; T2 x2; };......但它是否由标准保证?
C++ 具有小型结构调用约定优化,其中编译器在函数参数中传递小型结构与传递原始类型(例如,通过寄存器)一样有效。例如:
class MyInt { int n; public: MyInt(int x) : n(x){} };
void foo(int);
void foo(MyInt);
void bar1() { foo(1); }
void bar2() { foo(MyInt(1)); }
Run Code Online (Sandbox Code Playgroud)
bar1()并bar2()生成几乎相同的汇编代码,除了分别调用foo(int)和foo(MyInt)。特别是在 x86_64 上,它看起来像:
mov edi, 1
jmp foo(MyInt) ;tail-call optimization jmp instead of call ret
Run Code Online (Sandbox Code Playgroud)
但是如果我们测试std::tuple<int>,它会有所不同:
void foo(std::tuple<int>);
void bar3() { foo(std::tuple<int>(1)); }
struct MyIntTuple : std::tuple<int> { using std::tuple<int>::tuple; };
void foo(MyIntTuple);
void bar4() { foo(MyIntTuple(1)); }
Run Code Online (Sandbox Code Playgroud)
生成的汇编代码看起来完全不同,小尺寸的struct( std::tuple<int>)是通过指针传递的:
sub rsp, 24 …Run Code Online (Sandbox Code Playgroud) 我们的软件抽象出硬件,我们有代表这个硬件状态的类,并且有很多数据成员用于该外部硬件的所有属性.我们需要定期更新有关该状态的其他组件,为此我们通过MQTT和其他消息传递协议发送protobuf编码的消息.有不同的消息描述硬件的不同方面,因此我们需要发送这些类的数据的不同视图.这是一个草图:
struct some_data {
Foo foo;
Bar bar;
Baz baz;
Fbr fbr;
// ...
};
Run Code Online (Sandbox Code Playgroud)
让我们假设我们需要发送一条包含foo和的消息bar,并且一封包含bar和baz.我们目前的做法是大量的锅炉板:
struct foobar {
Foo foo;
Bar bar;
foobar(const Foo& foo, const Bar& bar) : foo(foo), bar(bar) {}
bool operator==(const foobar& rhs) const {return foo == rhs.foo && bar == rhs.bar;}
bool operator!=(const foobar& rhs) const {return !operator==(*this,rhs);}
};
struct barbaz {
Bar bar;
Baz baz;
foobar(const Bar& bar, const Baz& baz) : bar(bar), baz(baz) {}
bool …Run Code Online (Sandbox Code Playgroud) 我想使用一个三元组类,尽可能与std :: pair类似.STL似乎没有.我不想使用太重的东西,比如Boost.是否有一些有用的FOSS非限制性许可三联类可以从某个地方解除?我应该自己动手吗?我应该完全做些什么吗?
编辑:关于std::tuple......
特定于三胞胎的课程真的没有益处吗?我的意思是,有了元组,我做不到
template<typename T1, typename T2, typename T3> std::tuple<T1, T2, T3> triple;
Run Code Online (Sandbox Code Playgroud)
我可以吗?我不是必须键入dede个人类型组合三元组吗?
stdtuple ×10
c++ ×9
c++11 ×5
std-pair ×2
boilerplate ×1
c++17 ×1
c++20 ×1
iteration ×1
performance ×1
redundancy ×1
std ×1
triplet ×1
tuples ×1
x86 ×1