如何使用静态多态性在 int 和指针类型之间进行转换?
How can I use static polymorphism to convert between int and pointer types?
我有这段代码:
#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。我做错了什么?
这个函数
template<class T> void* ToPtr(T t) { return ToPtr((void*)t); }
无限期地调用自己...
ToPtr
不是此函数模板中的依赖名称(因为转换为 void*
永远不是类型依赖表达式 [temp.dep.expr]/3),因此,它被查找函数模板的定义点,而不是实例化点。由于 ToPtr
的其他重载中的 none 是在定义点声明的,函数模板最终会调用自身。确保 ToPtr
的所有重载都在定义函数模板之前声明...
除此之外,您绝对不要将指针转换为 unsigned int
或 int
,因为这些类型不能保证足够大以实际表示指针值。如果你真的必须这样做,请使用 std::uintptr_t or std::intptr_t...
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> 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)
当你的程序 "crashes" 时,你应该 运行 它在调试器中。您会非常清楚地看到堆栈溢出,因为数百个堆栈帧都将显示相同的递归调用。
我有这段代码:
#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。我做错了什么?
这个函数
template<class T> void* ToPtr(T t) { return ToPtr((void*)t); }
无限期地调用自己...
ToPtr
不是此函数模板中的依赖名称(因为转换为 void*
永远不是类型依赖表达式 [temp.dep.expr]/3),因此,它被查找函数模板的定义点,而不是实例化点。由于 ToPtr
的其他重载中的 none 是在定义点声明的,函数模板最终会调用自身。确保 ToPtr
的所有重载都在定义函数模板之前声明...
除此之外,您绝对不要将指针转换为 unsigned int
或 int
,因为这些类型不能保证足够大以实际表示指针值。如果你真的必须这样做,请使用 std::uintptr_t or std::intptr_t...
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> 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)
当你的程序 "crashes" 时,你应该 运行 它在调试器中。您会非常清楚地看到堆栈溢出,因为数百个堆栈帧都将显示相同的递归调用。