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


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

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

    other.h

    #pragma once
    
    #include 
    #include 
    
    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 
    #include 
    #include 
    
    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<(t));
    }
    else if (t.index() == 1)
    {
    	visitor(get(t));
    }
    else if(t.index() == 2)
    {
    	visitor(get(t));
    }
    
    or
    if (holds_alternative(t))
    {
    	visitor(get(t));
    }
    else if (holds_alternative(t))
    {
    	visitor(get(t));
    }
    else if(holds_alternative(t))
    {
    	visitor(get(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 
    #include 
    
    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,vector的形式放在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;
    		}
    	});
    }
    

    参考

  • 相关阅读:
    4种 Redis 集群方案及优缺点对比
    试试使用 Vitest 进行组件测试,确实很香。
    美创数据库安全审计DAS通过IPv6 Ready Logo认证
    Vue脚手架的使用(VCLI)
    63. 不同路径 II
    【PickerView案例13-应用程序对象介绍 Objective-C语言】
    【数模】Matlab allcycles()函数的源代码(2021a之前版本没有)
    2024.06.04 校招 实习 内推 面经
    设计模式的理解
    数学建模 -- 灰色预测模型
  • 原文地址:https://blog.csdn.net/u011436427/article/details/140368796