赞
踩
目录
二、std::tuple中的元素是在堆中创建的还是在栈中创建的
六、如何通过已有的std::tuple生成新的std::tuple
主要有如下4种方式:
- #include <iostream>
- #include <tuple>
- #include <string>
-
- using namespace std;
-
- static int cnt = 0;
-
- class Person {
-
- private:
- int id;
-
- public:
- string name;
- int age;
-
- Person() {
- id = ++cnt;
- cout << "Person()" << id <<endl;
- }
-
- Person(string _name, int _age): name(_name), age(_age) {
- id = ++cnt;
- cout << "Person(string _name, int _age)" << id << endl;
- }
-
- Person(const Person&) {
- id = ++cnt;
- cout << "Person(const Person&)" << id << endl;
- }
-
- Person(Person&&) {
- id = ++cnt;
- cout << "Person(Person&&)" << id << endl;
- }
-
- Person& operator=(const Person&) {
- cout << "operator=(const Person&)" << id << endl;
-
- return *this;
- }
-
- };
-
- int main () {
- {
- cout << "--------------------------------//(1)" << endl;
- tuple<int, bool, string, Person> t1 = tuple<int, bool, string, Person>(11, true, "ok", Person("ok", 11));
- }
- {
- cout << "--------------------------------//(2)" << endl;
- Person p("ok", 11);
- tuple<int, bool, string, Person> t2 = tuple<int, bool, string, Person>(11, true, "ok", p);
- }
- {
- cout << "--------------------------------//(3)" << endl;
- tuple<int, bool, string, Person> t3 = std::forward_as_tuple(11, true, "ok", Person("ok", 11));
- }
- {
- cout << "--------------------------------//(4)" << endl;
- Person p("ok", 11);
- tuple<int, bool, string, Person> t4 = std::forward_as_tuple(11, true, "ok", p);
- }
- {
- cout << "--------------------------------//(5)" << endl;
- tuple<int, bool, string, Person> t5 = std::make_tuple(11, true, "ok", Person("ok", 11));
- }
- {
- cout << "--------------------------------//(6)" << endl;
- Person p("ok", 11);
- tuple<int, bool, string, Person> t6 = std::make_tuple(11, true, "ok", p);
- }
- {
- cout << "--------------------------------//(7)" << endl;
- int i = 11;
- bool b = true;
- string s = "ok";
- Person p("ok", 11);
- tuple<int, bool, string, Person> t7 = std::tie(i, b, s, p);
- }
-
- return 1;
- }
执行结果如下:
--------------------------------//(1)
Person(string _name, int _age)1
Person(Person&&)2
--------------------------------//(2)
Person(string _name, int _age)3
Person(const Person&)4
--------------------------------//(3)
Person(string _name, int _age)5
Person(Person&&)6
--------------------------------//(4)
Person(string _name, int _age)7
Person(const Person&)8
--------------------------------//(5)
Person(string _name, int _age)9
Person(Person&&)10
Person(Person&&)11
--------------------------------//(6)
Person(string _name, int _age)12
Person(const Person&)13
Person(Person&&)14
--------------------------------//(7)
Person(string _name, int _age)15
Person(const Person&)16
从执行结果可以看到,(1)(3)的效率最高,(2)(4)(7)次之,(5)更低,(6)最差。也就是说,尽量使用std::tuple<>()和std::forward_as_tuple()通过内部元素使用右值引用构造的形式;尽量不要使用std::make_tuple()的任何形式。
std::tuple中的元素创建的区域是跟std::tuple创建的区域相同。如果std::tuple是在栈上创建的,则其中的元素也是在栈中创建的;如果std::tuple是在堆中创建的,则其中的元素也在堆中创建。
- template<typename Tuple>
- int getSize() {
- return std::tuple_size<Tuple>::value;
- };
- template<typename Tuple, int N>
- struct TypeGetter
- {
- using type = typename std::tuple_element<N, Tuple>::type;
- };
N表示tuple中的第N个元素
- #include <iostream>
- #include <tuple>
- #include <string>
-
- using namespace std;
-
- template<typename Tuple, int N = std::tuple_size<Tuple>::value>
- struct Printer
- {
- static void log(Tuple& t) {
- Printer<Tuple, N - 1>::log(t);
-
- using type = typename std::tuple_element<N - 1, Tuple>::type;
- std::string ts = typeid(type).name();
- type& v = std::get<N - 1>(t);
-
- std::cout << ts << ":" << v << std::endl;
- }
- };
-
- template<typename Tuple>
- struct Printer<Tuple, 1>
- {
- static void log(Tuple& t) {
- using type = typename std::tuple_element<0, Tuple>::type;
- std::string ts = typeid(type).name();
- type& v = std::get<0>(t);
-
- std::cout << ts << ":" << v << std::endl;
- }
- };
-
- int main() {
- std::tuple<int, bool, string> t = std::forward_as_tuple(11, true, "ok");
- Printer<std::tuple<int, bool, string>>::log(t);
-
- return 1;
- }
执行结果:
int:11
bool:1
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >:ok
上述代码通过定义结构体模板Printer,并对Printer做偏特化实现对tuple对象的遍历的。
主要有以下4种形式:
- tuple<int, bool, string, Person> swapTest() {
- {
- cout << "--------------------------------//(1)" << endl;
- tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
- cout << "--------------------------------" << endl;
- tuple<int, bool, string, Person> t1 = t0; // equal to tuple<int, bool, string, Person> t1(t0);
- }
- {
- cout << "--------------------------------//(2)" << endl;
- tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
- cout << "--------------------------------" << endl;
- tuple<int, bool, string, Person> t1 = move(t0); // equal to tuple<int, bool, string, Person> t1(move(t0));
- }
- {
- cout << "--------------------------------//(3)" << endl;
- tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
- cout << "--------------------------------" << endl;
- tuple<int, bool, string, Person> t1;
- cout << "--------------------------------" << endl;
- t1.swap(t0); // equal to std::swap(t1, t0);
- }
-
- cout << "--------------------------------//(4)" << endl;
- tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
- cout << "--------------------------------" << endl;
-
- return t0;
- }
-
- int main() {
- tuple<int, bool, string, Person> t = swapTest();
- cout << "--------------------------------" << endl;
- return 1;
- }
运行结果:
----------------------------------------------------------------//(1)
Person(string _name, int _age)1
Person(Person&&)2
--------------------------------
Person(const Person&)3
----------------------------------------------------------------//(2)
Person(string _name, int _age)4
Person(Person&&)5
--------------------------------
Person(Person&&)6
----------------------------------------------------------------//(3)
Person(string _name, int _age)7
Person(Person&&)8
--------------------------------
Person()9
--------------------------------
Person(Person&&)10
operator=(const Person&)9
operator=(const Person&)8
----------------------------------------------------------------//(4)
Person(string _name, int _age)11
Person(Person&&)12
--------------------------------
Person(Person&&)13
--------------------------------
从运行结果中可以看到,(2)(4)效率最高,元素都是采用转移构造函数创建的,(1)次之,(3)最差。当然(3)性能最差是有原因,它毕竟是交换,需要双向赋值。
可以使用T make_from_tuple(Tuple&& t)(C++17),并且对象要的一个类型和顺序与std::tuple中元素的类型和顺序相同的构造函数。
1.拆解成可变参数函数
- //void print()
- //{
- // cout << endl;
- //}
- //
- //template <typename HeadType, typename... Types >
- //void print(HeadType arg, Types... Args)
- //{
- // cout << typeid(HeadType).name() << ":" << arg << endl;
- //
- // print(Args...);
- //}
-
- template < typename Tuple, typename... Types >
- constexpr void tuple_element_type(Tuple&& t, Types... Args)
- {
- // print(Args...);
- }
-
- template<typename Tuple, std::size_t... I>
- constexpr void tuple_element_index(Tuple&& t, std::index_sequence<I...>)
- {
- tuple_element_type(t, std::get<I>(std::forward<Tuple>(t))...);
- }
-
- template <typename Tuple>
- constexpr void break_tuple(Tuple&& t)
- {
- tuple_element_index(t, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
- }
最终,将std::tuple中的元素拆解到方法void tuple_element_type(Tuple&& t, Types... Args)中。
2.拆解成变量
- int main() {
- std::tuple<int, std::string, bool> t(121, "dds", true);
-
- int i;
- std::string s;
- bool b;
-
- std::tie(i, s, b) = t;
-
- cout << "i=" << i << endl;
- cout << "s=" << s << endl;
- cout << boolalpha << "b=" << b << endl;
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。