c++函数,它在不使用模板的情况下接受任何数据类型
c++ function that takes any data type without using templates?
我有一个赋值,它要求为任何数据类型编写一个函数。该函数应该打印结构的字节,识别数据结构使用的字节总数,并区分用于成员的字节和用于填充的字节。
我的第一反应,和大多数类的反应一样,就是使用模板。这允许您编写一次函数,并收集传递到函数中的对象的运行时类型。使用memset和typeid可以很容易地完成所要求的内容。然而,我们的教授刚刚看到了我们关于模板和该死的模板的讨论。
看到这件事后,我陷入了困境,我正在寻找一点指导,作为绕过这件事的最佳方式。我研究过的一些事情:
- 带有显式类型转换的void指针(这看起来会很混乱)
- 基类只有虚拟函数,所有数据结构都从中继承,这样做似乎有点奇怪
- 与我们的每个数据结构都有"友谊"的基类
- 为问题集中的每个数据结构重写一个函数(我认为这是最糟糕的解决方案)
希望我忽略了一个常见的c++工具,有人有什么想法吗?
尽可能愚蠢地对待函数,事实上,把它当作什么都不知道,所有信息都必须传递给它。
功能参数:
- 结构地址,作为
uint8_t *
。(需要打印字节) - 结构大小,以字节为单位。(需要打印字节并打印总尺寸)
- 成员信息的向量:成员长度或成员使用的字节数之和
需要向量来满足打印成员使用的字节和填充使用的字节的要求。您可以选择传递成员的总和。
示例:
void Analyze_Structure(uint8_t const * p_structure,
size_t size_of_structure,
size_t size_occupied_by_members);
这个赋值的技巧是找出如何让调用函数确定这些项。
希望这能有所帮助。
编辑1:
struct Apple
{
char a;
int weight;
double protein_per_gram;
};
int main(void)
{
Apple granny_smith;
Analyze_Structure((uint8_t *) &granny_smith,
sizeof(Apple),
sizeof(granny_smith.a)
+ sizeof(granny_smith.weight)
+ sizeof(granny_smith.protein_per_gram);
return 0;
}
我有一个任务,要求为任何数据类型编写一个函数。
这意味着要么是模板(你的教授驳回了),要么是void*,要么是可变数量的参数(类似于printf)。
该功能应该打印结构的字节
void your_function(void* data, std::size_t size)
{
std::uint8_t* bytes = reinterpret_cast<std::uint8_t*>(data);
for(auto x = bytes; x != bytes + size; ++x)
std::clog << "0x" << std::hex << static_cast<std::uint32_t>(*x) << " ";
}
[…],并标识数据结构使用的字节总数,同时区分用于成员的字节和用于填充的字节。
在这一点上,我迷失了方向:用于填充的字节(根据定义)不是结构的一部分。考虑:
struct x { char c; char d; char e; }; // sizeof(x) == 3;
x instance{ 0, 0, 0 };
your_function(&instance, sizeof(x)); // passes 3, not 4 (4 for 32bits architecture)
理论上,您也可以将alignof(instance)
传递给函数,但这不会告诉您内存中字段的对齐方式(据我所知,它还没有标准化,但我可能错了)。
这里有几种可能性:
你的教授学会了";"黑客";C++,在10或20年前被认为是好代码,但没有更新他的知识(C风格的代码、指针、直接内存访问和"智能黑客"都在这里)。
他不知道如何准确地表达自己想要的东西,也不知道使用什么术语("为任何数据类型编写函数"太模糊了:作为一名开发人员,如果我得到了这项任务,首先要做的就是询问细节,比如"如何使用它?"answers"期望的函数签名是什么")。
例如,这可以通过宏在一定程度上实现,但如果他希望你用宏代替函数和模板,你可能应该考虑更换教授。
他的意思是,你应该编写一些任意的数据类型(比如我上面的
struct x
),并围绕它定义你的API(不太可能)。
我不确定这样的函数是否可以在没有最少内省的情况下构建:你需要知道结构成员是什么,否则你只能访问结构的大小。
不管怎样,这是我的建议,只要代码的用户"合作",就可以在不进行内省的情况下工作。
函数将使用void*和size_t作为结构的地址和sizeof的参数。
0)允许用户创建所需类型的结构。
1) 让用户调用一个将所有字节设置为0的函数。
2) 让用户为结构的每个字段分配一个值。
3) 让用户调用您的一个函数,该函数会记录仍为0的每个字节。
4) 让用户调用一个将所有字节设置为1的函数。
5) 让用户再次为结构的每个字段分配一个值。(与第一次相同的值!)
6) 让用户调用您的函数,并计算之前标记为1 and的字节。这些是填充字节。
尝试先使用值0,然后使用值1的原因是用户分配的值可能包括字节0;但它们不能同时是字节0和字节1,因此其中一个测试将排除它们。
struct _S { int I; char C } S;
Fill0(S, sizeof(S));
// User cooperation
S.I= 0;
S.C= ' ';
Mark0(S, sizeof(S)); // Has some form of static storage
Fill1(S, sizeof(S));
// User cooperation
S.I= 0;
S.C= ' ';
DetectPadding(S, sizeof(S));
您可以将所有这些打包到一个函数中,该函数采用回调函数参数来执行成员分配。
void Assign(void* pS) // User-written callback
{
struct _S& S= *(struct _S)pS;
S.I= 0;
S.C= ' ';
}
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- 为什么在这种情况下,bool 类型的输出等于 0?
- QT QOpenGLWidget:如何在不使用数据块复制的情况下修改VBO中的单个顶点值?
- C++默认情况下,指针类型数组的元素是否保证初始化为 nullptr?
- 如何在没有实例的情况下获取非静态方法的类型?
- 如何在不破坏现有应用程序的情况下更改 API 中 stl 容器的数据类型?
- 是否可以在不使用 decltype 的情况下推断先前定义的 extern 变量的类型
- 将类型映射到整数值后,如何在给定整数值的情况下恢复类型?
- 如何在没有性能命中的情况下抽象SIMD代码来处理不同的数据类型
- 为什么在auto和template函数的情况下,类型都没有推导为"const"类型
- GDB有没有办法在不省略模板参数的情况下打印类型
- 在不更改数据类型的情况下可逆地组合两个uint32_t
- 在不更改位的情况下更改类型
- 一个向量在两种不同的情况下可以容纳不同的数据类型吗
- c++函数,它在不使用模板的情况下接受任何数据类型
- 如何在不在类对象中重新定义类类型的情况下将数据类型定义为结构中的int
- 获取和设置内部数据:返回类型,错误情况下的行为
- 是否有可能在没有编译失败的情况下推断类型是否不完整
- 歧义情况下的类型名解析
- 在不丢失数据的情况下改变帧类型