简体   繁体   English

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

[英]How can I use static polymorphism to convert between int and pointer types?

I have this piece of code:我有这段代码:

#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;
}

The program crashes in the first call to Find() but I'm not sure why.程序在第一次调用 Find() 时崩溃,但我不知道为什么。 I'm using GCC 6.2.0, which is only C++14 compliant, otherwise I'd use constexpr.我正在使用 GCC 6.2.0,它仅与 C++14 兼容,否则我将使用 constexpr。 What am I doing wrong?我究竟做错了什么?

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

This calls itself.这叫自己。 Forever.永远。

Since non-templates are preferred over templates, this is really easy to fix: you just have to put the non-templates first so that they're in scope within the overload above:由于非模板比模板更受欢迎,这真的很容易解决:您只需将非模板放在首位,以便它们在上面的重载范围内:

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 ) 现场演示

When your program "crashes", you should be running it in a debugger.当您的程序“崩溃”时,您应该在调试器中运行它。 You'd have seen the stack overflow quite clearly, as hundreds of stack frames would all show the same recursive call.您已经非常清楚地看到堆栈溢出,因为数百个堆栈帧都会显示相同的递归调用。

This function这个功能

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

calls itself indefinitely…无限期地自称……

ToPtr is not a dependent name inside this function template (because a cast to void* is never a type-dependent expression [temp.dep.expr]/3 ), thus, it is looked up at the point of definition of the function template, not at the point of instantiation. ToPtr不是此函数模板中的依赖名称(因为转换为void*永远不是依赖于类型的表达式[temp.dep.expr]/3 ),因此,在函数模板的定义点查找它,而不是在实例化点。 Since none of the other overloads of ToPtr are declared at the point of definition, the function template ends up calling itself.由于在定义时没有声明ToPtr的其他重载,因此函数模板最终会调用自身。 Make sure that all overloads of ToPtr are declared before the definition of your function template…确保在定义函数模板之前声明ToPtr所有重载......

Apart from that, you should really never convert pointers to unsigned int or int as these types are not guaranteed to be large enough to actually represent a pointer value.除此之外,您真的不应该将指针转换为unsigned intint因为这些类型不能保证足够大以实际表示指针值。 Use std::uintptr_t or std::intptr_t for that if you really must do it…如果你真的必须这样做,请使用std::uintptr_t 或 std::intptr_t ......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM