【问题标题】:how to remove const from member function template type signature?如何从成员函数模板类型签名中删除 const?
【发布时间】:2011-03-25 15:25:29
【问题描述】:

我正在研究一些 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

【问题讨论】:

  • “从成员函数中删除 const 限定符的正确方法是什么,以便我可以获得函数类型签名?”成员函数是其签名的一部分。
  • 我不知道你想要这个做什么,但是静态和非静态成员函数的签名不同的。我发现前两行的输出比第三行不同的事实更糟糕。你真正想解决的问题是什么?
  • typeid 中的 name() 完全是特定于实现的。你怎么能说哪个是对的或错的?
  • @BoPersson 你没抓住重点。
  • GCC 打印的类型是错误的(基于 c++filt 完成的拆解)。第三个应该是int() const,但它说是int()

标签: c++ templates visual-c++ g++ metaprogramming


【解决方案1】:

我建议你看看 Alexandrescu 的 loki 库的 TypeTraits.h。 它提供了一种去除限定符的通用方法,例如 const。

http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/TypeTraits.h?view=markup

当我对元编程 c++ 元编程有一些哲学问题时,我倾向于查看现代 c++ 设计,如果我的下落有答案的话。

【讨论】:

  • 这解决了我的问题。不是我喜欢的方式,但它表明我不能用几行代码做我需要的事情。谢谢!
【解决方案2】:

这个会有所帮助:

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

【讨论】:

  • 这实际上是行不通的。这会导致 R 匹配返回类型,而不是函数类型。
  • 我明白了......然后我怀疑它应该是可编译的:为什么R (T::*) 中的R 应该是“函数类型”?
  • 我不确定这个语法是怎么回事(我从来没有使用过指向成员函数的指针),但这很有效。有趣的是——我确信R (T const::*) 应该可以工作(因为它应该是const 类型的T)但是那行不通……
  • @Konrad 如果你在一个类中有一个void f() const { },那么这定义了一个类型为void() const的成员。因此,如果你获取类 C 的成员指针,你会得到一个void (C::*)() const,或者用另一种方式表示,一个R C::*,其中R 是一个void() const。这与说RU const 不同,其中Uvoid():没有 const 函数类型。函数类型末尾的 const 不会使函数“不可修改”等。
  • 这也不等于Rvoid()Cconst U。你所拥有的是类C 的成员指针。不是类类型const U。成员具有特定类型,而不是类。
【解决方案3】:

typeid(...).name() 返回实现定义的字符串。它可能是编译器损坏的符号,也可能是 Jon Skeet 写的一首诗。请不要依赖它来做任何有用的事情。

想要去掉“const”似乎也很奇怪;函数 const,那你为什么不希望在结果字符串中使用它呢?

我不知道您为什么期待或看到“FIvE”。我在你的代码中看不到类似的东西。

【讨论】:

  • FivE 是一种错位类型。使用 GNU 解码器,c++filt FivE 给出了int ()()
猜你喜欢
  • 2023-04-05
  • 1970-01-01
  • 2018-12-16
  • 2016-05-01
  • 2014-06-06
  • 2018-08-20
  • 1970-01-01
  • 1970-01-01
  • 2020-09-29
相关资源
最近更新 更多