假设这是我的图书馆。这是一个非常庞大的图书馆:
library.hpp
template<class usertype> void function_name(usertype aaa)
{
}
这是我的主要
int main()
{
int x=3;
function_name(x);
double y=3.5;
function_name(y);
return 0;
}
我不知道图书馆里面发生了什么。我想要的是转换库以适应我的代码。实际上,将模板缩减为实际代码。
我需要将上面的库代码转换为:
void function_name(int aaa)
{
}
void function_name(double aaa)
{
}
所以我可以根据自己的需要操纵库,而不是操纵适用于每个人的通用代码。如何完成从模板到实际代码的转换(无需手动操作,但以自动方式)?
修改
我想将整个文件library.hpp
转换为不包含模板的library_2.hpp
。相反,有两个真正实现的功能。这是在编译过程中发生的事情。
我不希望减少编译时间。我正在处理一个由196个文件组成的庞大的库。在图书馆的许多功能中,我需要一些与我的工作相关的功能。我打算破解并扩展这个库。扩展整个库对我来说是一项巨大的努力成本。我只想扩展我需要的东西。因此,对我来说非常重要的是减少代码并简化代码并删除所有模板,用显式代码替换它们。 我不擅长C ++和编译器错误。所以,在如此庞大的库中,我更喜欢使用自动方法而不是涉及手动代码操作。我也不擅长理解这个图书馆。要理解库,最好将其复杂的函数转换为与我真正需要的相关的显式实现代码。然后我可以更好地理解别人的代码。我将删除与我的需求无关的功能。我也不关心图书馆的更新。一旦我建立新的图书馆,它的维护是我的职责。新的库将更小,更易于维护。评论显示,有些人从不同的角度看待我的目标。我希望这个解释清楚。
如果有好奇心,我要操纵的库odeint与数学计算有关,很少有变化或内部错误。
答案 0 :(得分:2)
我不完全确定你想要实现什么,但是通过阅读评论,我认为你主要担心的是你正在尝试减少编译时间并减少与模板相关的错误消息。您不尝试为您自己的类型专门化库函数。
如果您只使用少数类型从库中实例化模板化函数,则可以使用简单的方法从图片中获取模板。但是它会强制你为模板化函数和你想要使用的类型组合编写两行代码。
创建自己的头文件library_wrapper.hpp
。在那里,您声明了要使用的函数的非模板版本。
<强> library_wrapper.hpp
强>
#ifndef LIBRARY_WRAPPER_H
#define LIBRARY_WRAPPER_H
#include <vector> // just an example
namespace library_wrapper
{
void
function_name(int);
void
function_name(double);
int
another_function(const std::vector<double>&, bool);
}
#endif
然后使用您最喜爱的模板库“一次性”实现它们。
<强> library_wrapper.cpp
强>
#include "library_wrapper.hpp"
#include <library.hpp> // the template library
namespace library_wrapper
{
void
function_name(const int arg1)
{
return library::function_name(arg1);
}
void
function_name(const double arg1)
{
return library::function_name(arg1);
}
int
another_function(const std::vector<double>& arg1, const bool arg2)
{
return library::function(arg1, arg2);
}
}
您编译library_wrapper.cpp
一次,对抗模板,然后继续仅使用提供非模板化函数的包装器。
请注意,这种方法会危及模板如此快速的主要原因之一:内联。您的包装函数无法在编译时内联,因为您正在从编译器中隐藏它们的定义。这是有目的的,另一方面,可以缩短编译时间。链接时内联可能会给你一些内联,但你不应该把它视为理所当然。
请注意,此解决方案与 types (与 functions 相反)的效果不佳。您可以尝试编写一些pimpl-wrappers但我不建议这样做。也许最好的事情就是成为模板库的朋友......
我正在处理一个由196个文件组成的庞大的库。在图书馆的许多功能中,我需要一些与我的工作相关的功能。
在好奇的情况下,我要操纵的库是与数学计算有关的odeint,很少有变化或内部错误。
这看起来上述方法确实有帮助。
扩展整个库对我来说需要付出巨大的努力。我只想扩展我需要的东西。因此,对我来说非常重要的是减少代码并简化代码并删除所有模板,用显式代码替换它们。
我认为这不是一个好方法。相反,将库用作黑盒子并在其上构建自己的库。将开发人员的精力集中在新功能上,并从底层库的更新中受益。
我认为有问题的图书馆是免费软件(否则,你想做的事情无论如何都是非法的),自由软件项目应该相互支持。如果你在库X之上构建一个很棒的库Y,那么两者都是 项目,X和Y,可以受益。另一方面,如果您只删除其他库的一部分并添加其他功能,那么您的两个竞争项目可能最终都会变得不完整且不兼容,这对您和您的用户来说都是令人沮丧的。
要理解库,最好将其复杂的函数转换为与我真正需要的相关的显式实现代码。然后我可以更好地理解别人的代码。
我认为你不能合理地期望某些机器生成的代码比原始的人工编写的代码更具可读性。毕竟,人类编码人员被教导为人类编写代码,但编译器会针对其他方面进行优化。
我不擅长C ++和编译器错误。 [...]我也不擅长理解这个图书馆。
我打算破解并扩展这个库。
我也不关心图书馆的更新。建立新图书馆后,维护是我的职责。
我不想看起来粗鲁但是......你看到了这个问题吗?
答案 1 :(得分:0)
专业化
template<>
void function_name(int aaa)
{
}
template<>
void function_name(double aaa)
{
}
示例代码
#include <iostream>
template<class usertype>
void function_name(usertype aaa)
{
std::cout << "default\n";
}
template<>
void function_name(int aaa)
{
std::cout << "int value = " << aaa << '\n';
}
template<>
void function_name(double aaa)
{
std::cout << "double value = " << aaa << '\n';
}
int main()
{
int x = 3;
function_name(x);
double y = 3.5;
function_name(y);
struct Z{} z;
function_name(z);
return 0;
}