我正在尝试一种新的方法来回答this question,我认为返回成员函数的地址作为ID可能是值得探索的路径:
struct S
{
template <typename T>
void f(){};
using mp = void(S::*)();
template <typename T>
static constexpr mp ID()
{
return &S::f<T>;
}
};
我认为S::f
的每个实例都将具有一个唯一的地址,该地址将在每个翻译单元中共享,甚至可能在编译时可用,因此我对其进行了测试:
std::cout << S::ID<char>() << '\n';
输出为1
;说实话,这是非常出乎意料的(我期望值像其他指针一样被打印为十六进制数字),但是我尝试了其他类型:
std::cout << S::ID<char>() << '\n'; // Prints '1'.
std::cout << S::ID<char>() << '\n'; // Expecting '1', got '1'.
std::cout << S::ID<short>() << '\n'; // Execting something different to '1', got '1'.
这时,我意识到1
的值不是“对象内部成员函数的地址”,因为两个不同的函数(void S::f<char>()
和{ {1}})共享了相同的地址。因此,我尝试了另一种方法:
void S::f<short>()
无捕获的lambda可以转换为函数指针,并且即使每个lambda的内容相同,每个lambda也具有唯一的类型,因此我期待一些随机的 ish 值,但又得到了struct S
{
template <typename T>
static auto ID()
{
return +[]{};
}
};
:
1
在这一点上,我只是想知道这些std::cout << S::ID<char>() << '\n'; // Expecting '0x????????' Prints '1'.
std::cout << S::ID<char>() << '\n'; // Expecting '0x????????' Prints '1'.
std::cout << S::ID<short>() << '\n'; // Expecting '0x!!!!!!!!' Prints '1'.
的含义,以及为什么所有这些1
都是如此,即使 expected 的行为是它们都必须屈服一个不同的值。