我正在研究一些C ++类型系统的东西,并且我在从成员函数中删除const-ness以与函数特征类一起使用时遇到问题。真正令人难以置信的是,这对G ++运行良好,但是MSVC10无法正确处理部分特化,我不知道其中一个编译器是否真的有错误。
这里的问题是,从成员函数中删除const限定符的正确方法是什么,以便我可以获得函数类型签名?
采用以下代码示例:
#include <iostream>
template<typename T> struct RemovePointer { typedef T Type; };
template<typename T> struct RemovePointer<T*> { typedef T Type; };
template<typename R,typename T> struct RemovePointer<R (T::*)> { typedef R Type; };
class A {
public:
static int StaticMember() { return 0; }
int Member() { return 0; }
int ConstMember() const { return 0; }
};
template<typename T> void PrintType(T arg) {
std::cout << typeid(typename RemovePointer<T>::Type).name() << std::endl;
}
int main()
{
PrintType(&A::StaticMember);
PrintType(&A::Member);
PrintType(&A::ConstMember); // WTF?
}
所有这三个PrintType语句都应该打印相同的东西。 MSVC10打印以下内容:
int __cdecl(void)
int __cdecl(void)
int (__cdecl A::*)(void)const __ptr64
g ++打印这个(这是预期的结果):
FivE
FivE
FivE
答案 0 :(得分:3)
我建议你看看Alexandrescu的loki图书馆的TypeTraits.h。 它提供了一种剥离限定符的通用方法,例如const。
http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/TypeTraits.h?view=markup
当我对元编程c ++元编程有一些哲学问题时,如果对我的行踪有答案,我倾向于使用现代c ++设计。
答案 1 :(得分:1)
这个会有所帮助:
template<typename R,typename T> struct RemovePointer<R (T::*)() const> { typedef R Type; };
请注意,您可能也希望在前一行中添加()
(否则它将匹配指向成员的指针和指向函数的指针):
template<typename R,typename T> struct RemovePointer<R (T::*)()> { typedef R Type; };
答案 2 :(得分:1)
typeid(...).name()
返回实现定义的字符串。它可能是编译器错位的符号,也可能是Jon Skeet编写的一首诗。请不要依赖它来做任何有用的事情。
想要取消“const”似乎也很奇怪;函数是 const
,那么为什么你不想在结果字符串中使用它呢?
我不知道你为什么期待或看到“FIvE”。我在你的代码中看不到类似的东西。