【c++11】cpp实现模板函数的声明与定义分离

devtools/2024/10/16 4:29:42/

文章目录

  • 一、分离模板的声明与定义方法一
  • 二、分离模板的声明与定义方法二
  • 参考

一、分离模板的声明与定义方法一

在模板定义的cpp文件中声明其特化版本

other.h

#pragma once#include <iostream>
#include <string>using namespace std;template<typename T>
void show(T t);

oher.cpp

#include "other.h"
template<typename T>
void show(T t)
{cout<<"t"<<'\n';
}template void show<int>(int);
template void show<double>(double);
template void show<string>(string);

二、分离模板的声明与定义方法二

使用variant(C++17语法)代替上述的方式

other.h

#pragma once
#include <iostream>
#include <string>
#include <variant>using namespace std;void show(variant<int , double, string> t);

other.cpp

#include "other.h"void show(variant<int , double, string> t)
{cout << t.index() <<endl;
/*
visit内部的实现方式可能就是通过index()选择的;
auto visitor = [](auto&& arg){cout<<arg<<endl;};if (t.index() == 0)
{visitor(get<int>(t));
}
else if (t.index() == 1)
{visitor(get<double>(t));
}
else if(t.index() == 2)
{visitor(get<string>(t));
}or
if (holds_alternative<int>(t))
{visitor(get<int>(t));
}
else if (holds_alternative<double>(t))
{visitor(get<double>(t));
}
else if(holds_alternative<string>(t))
{visitor(get<string>(t));
}
*/visit([](auto&& arg){cout<<args<<endl;},t);
}

解决了分离模板的声明与实现后,如果想要把每个variant对象保存至vector,出现的问题是:每个variant=32+8,string bytes+index bytes。每次占用内存过大,需要优化。所以使用data-oriented design进行改造

other.h

#pragma once#include <string>
#include <variant>using namespace std;using Object = variant<int, double, string>;void add_object(Object o);
void print_objects();

other.cpp

#include "other.h"
#Include <vector>static vector<variant<int.double.string>> objects;
static vector<int> int_objects;
static vector<double> double_objects;
static vector<string> string_objects;static constexpr int v = sizeof(variant<int.double.string>);void add_object(variant<int.double.string> o)
{objects.push_back(o);objects
}void print_objects()
{for(auto&& o : objects){visit([](auto&& arg){std::cout<<arg<<std::endl;},o);}
}

在这里插入图片描述

other.cpp

#include "other.h"
#Include <vector>static vector<int> int_objects;
static vector<double> double_objects;
static vector<string> string_objects;void add_object(variant<int,double,string> o)
{if(holds_alternatibe<int>(o)){int_objects.push_back(get<int>(o));}else if(holds_alternatibe<double>(o)){double_objects.push_back(get<double>(o));}else if(holds_alternatibe<string>(o)){string_objects.push_back(get<string>(o));}
}void print_objects()
{for(auto&& o: int_objects){cout<<o<<endl;}for(auto&& o: double_objects){cout<<o<<endl;}for(auto&& o: string_objects){cout<<o<<endl;}
}

使用编译器for循环以及tuple简化代码

static tuple<vector<int>. vector<double>, vector<string>> objects;void add_object(variant<int, double, string> o)
{if (o.index() == 0){std::get<0>(objects).push_back(std::get<0>(o));}else if (o.index() == 1){std::get<1>(objects).push_back(std::get<1>(o));}else 	if (o.index() == 2){std::get<2>(objects).push_back(std::get<2>(o));}
}void print_objects()
{for(auto&& o: std::get<0>(objects)){cout<<o<<endl;}for(auto&& o: std::get<1>(objects)){cout<<o<<endl;}for(auto&& o: std::get<2>(objects)){cout<<o<<endl;}
}

other.cpp

static tuple<vector<int>. vector<double>, vector<string>> objects;template<int N>
struct int_constant{static constexpr int value = N;
};template <int N, typename Lambda>
void static_for(Lambda&& lambda)
{if constexpr (N > 0){static_for<N-1>(lambda);int_constant<N-1> ic;lambda(ic);}
}void add_objects(variant<int, double, string> o)
{static_for<3>([&](auto ic){std::get<ic.value>(objects).push_vack(std::get<ic.value>(o));});
}void print_objects()
{static_for<3>([&](auto ic){for(auto&& o: std::get<ic.value>(objects)){cout<<o<<endl;}});
}

取出variant中的所有类型,以vector<x>,vector<y>的形式放在tuple中的类型中。即Object类型->Objects类型

other.cpp

template <class V>
struct variant_to_tuple_of_vector
{
}template <class ...Ts>
struct variant_to_tuple_of_vector<variant<Ts...>> {using type = tuple<vector<Ts>...>;
};static variant_to_tuple_of_vector<Object>::type objects;

自动提取variant中所有参数的个数,优化lambda只在输入的variant变量中插入

other.cpp

void add_objects(variant<int, double, string> o)
{static_for<std::variant_size_v<decltype(o)>>([&](auto ic){if (o.index() == ic.value){std::get<ic.value>(objects).push_vack(std::get<ic.value>(o));}});
}void print_objects()
{static_for<std::variant_size_v<decltype(o)>([&](auto ic){for(auto&& o: std::get<ic.value>(objects)){cout<<o<<endl;}});
}

参考

  • 【C++模板课】闭源软件能否元编程?
  • code

http://www.ppmy.cn/devtools/58734.html

相关文章

深入解析【C++ list 容器】:高效数据管理的秘密武器

目录 1. list 的介绍及使用 1.1 list 的介绍 知识点&#xff1a; 小李的理解&#xff1a; 1.2 list 的使用 1.2.1 list 的构造 知识点&#xff1a; 小李的理解&#xff1a; 代码示例&#xff1a; 1.2.2 list 迭代器的使用 知识点&#xff1a; 小李的理解&#xff1…

自动驾驶决策和控制系统的研究

摘要 自动驾驶汽车的决策和控制系统是实现自主驾驶的核心部分。本文详细探讨了自动驾驶系统中决策和控制的基本原理、主要方法及其在实际应用中的挑战与前景。通过对路径规划、行为决策、运动控制等关键环节的分析&#xff0c;本文旨在为自动驾驶技术的发展提供理论基础和实践指…

新手教学系列——高效管理MongoDB数据:批量插入与更新的实战技巧

前言 在日常开发中,MongoDB作为一种灵活高效的NoSQL数据库,深受开发者喜爱。然而,如何高效地进行数据的批量插入和更新,却常常让人头疼。今天,我们将一起探讨如何使用MongoDB的bulk_write方法,简化我们的数据管理流程,让代码更加简洁高效。 常规做法:find、insertone…

SpringBoot+Vue(2)excel后台管理页面

一、需求 SpringBootVue写excel后台管理页面&#xff08;二级页面打开展示每一个excel表&#xff0c;数据库存储字段为“下载、删除、文件详情、是否共享、共享详情”&#xff09; 二、解答 后端(Spring Boot) 1. 项目设置 使用Spring Initializr创建一个新的Spring Boot项目…

springboot零食盒子-计算机毕业设计源码50658

目 录 1 绪论 1.1 研究背景 1.2研究意义 1.3论文结构与章节安排 2 微信小程序的零食盒子系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 2.5本章小结 3 微信…

mac ssh连接工具

在Mac上&#xff0c;有多个SSH连接工具可供选择&#xff0c;这些工具根据其功能和适用场景的不同&#xff0c;可以满足不同用户的需求。以下是一些推荐的SSH客户端软件&#xff1a;12 iTerm2&#xff1a;这是一款功能强大的终端应用程序&#xff0c;提供了丰富的功能和定制选项…

【android 9】【input】【10.发送按键事件4——View的分发流程】

系列文章目录 可跳转到下面链接查看下表所有内容https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501文章浏览阅读2次。系列文章大全https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5501 目录…

自动驾驶---Perception之Occupancy

1 背景 在阐述Occupancy之前&#xff0c;先理解为什么要使用Occupancy&#xff1f; 如果自动驾驶车辆在行驶过程中看到的物体不是数据集的一部分&#xff0c;这个时候容易出现误判。 而在基于激光雷达的系统中&#xff0c;由于检测到点云&#xff0c;可以确定障碍物的存在&…