如何使用静态多态性在 int 和指针类型之间进行转换?

Posted

技术标签:

【中文标题】如何使用静态多态性在 int 和指针类型之间进行转换?【英文标题】:How can I use static polymorphism to convert between int and pointer types? 【发布时间】:2020-01-04 23:59:04 【问题描述】:

我有这段代码:

#include <iostream>

template<class T> void* ToPtr(T t)  return ToPtr((void*)t); 
void* ToPtr(void* i)  return i; 
void* ToPtr(int i)  return (void*)(long)(unsigned int)i; 

template<class T> int ToInt(T t)  return ToInt((void*)t); 
int ToInt(void* i)  return (int)(unsigned int)(long)i; 
int ToInt(int i)  return i; 

struct MyClass 
  template<class T>
  void* Find(T t)  return ToPtr(t); 

  template<class T>
  int FindInt(T t)  return ToInt(t); 
;

int main() 
  MyClass myClass;
  int myInt = 1;
  std::cout << &myClass << std::endl;
  std::cout << myInt << std::endl;
  std::cout << myClass.Find(&myClass) << std::endl;
  std::cout << myClass.Find(myInt) << std::endl;
  std::cout << myClass.FindInt(&myClass) << std::endl;
  std::cout << myClass.FindInt(myInt) << std::endl;

程序在第一次调用 Find() 时崩溃,但我不知道为什么。我正在使用 GCC 6.2.0,它仅符合 C++14,否则我会使用 constexpr。我做错了什么?

【问题讨论】:

您可能应该在这里解释您要做什么。连续进行 3 次 c 样式转换的原因是什么?某种促销技巧? 你的目标是什么? 什么样的“崩溃”?实际发生了什么? 您的模板ToPtr 将无法找到在它之后声明的函数。您正在递归调用模板版本到无穷大。 我的应用程序有一些遗留代码,它们同时接受 int 和 void* 并将它们存储在 void* 数据结构中。现在,每个版本的函数只复制了一堆函数。我正在尝试通过使用模板来生成变体来减少列表。 【参考方案1】:
template<class T> void* ToPtr(T t)  return ToPtr((void*)t); 

这会调用自己。永远。

由于非模板比模板更受欢迎,这很容易解决:您只需将非模板放在 first 以便它们在上述重载的范围内:

void* ToPtr(void* i)  return i; 
void* ToPtr(int i)  return (void*)(long)(unsigned int)i; 
template<class T> void* ToPtr(T t)  return ToPtr((void*)t); 

int ToInt(void* i)  return (int)(unsigned int)(long)i; 
int ToInt(int i)  return i; 
template<class T> int ToInt(T t)  return ToInt((void*)t); 

(live demo)

当您的程序“崩溃”时,您应该在调试器中运行它。您会非常清楚地看到堆栈溢出,因为数百个堆栈帧都会显示相同的递归调用。

【讨论】:

【参考方案2】:

这个函数

template<class T> void* ToPtr(T t)  return ToPtr((void*)t); 

无限期地调用自己……

ToPtr 不是此函数模板中的依赖名称(因为转换为 void* 绝不是依赖类型的表达式 [temp.dep.expr]/3),因此,在函数模板的定义点查找它,而不是在实例化点。因为ToPtr 的其他重载都没有在定义点声明,所以函数模板最终会调用自己。确保 ToPtr 的所有重载都在函数模板的定义之前声明...

除此之外,您真的不应该将指针转换为unsigned intint,因为这些类型不能保证足够大以实际表示指针值。如果您确实必须这样做,请使用std::uintptr_t or std::intptr_t...

【讨论】:

以上是关于如何使用静态多态性在 int 和指针类型之间进行转换?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用三元运算符创建指向多态类的唯一指针?

虚函数表指针与多态

虚函数表指针与多态

指针重新分配和多态

2017/03/24学习笔记

利用虚函数实现多态的方式:动态绑定