可以在编译时隐式引用类名吗?

Posted

技术标签:

【中文标题】可以在编译时隐式引用类名吗?【英文标题】:Can class name be referenced implicitly at compile-time? 【发布时间】:2020-03-04 11:13:21 【问题描述】:

有没有办法在编译时隐式引用类名?

具体来说,如果我想在class B 的范围内使用class B 声明template class A 的实例,有没有办法避免在声明class A 的语法中显式引用“B”实例?

用一个例子更好地说明:

// main.cpp

#include <iostream>

using namespace std;

template <typename T>
class A

public:
  typedef void (T::*TFunc)();

  A( T& t ) : t_( t ) 

  void callFunc( TFunc tFunc )  (t_.*tFunc)(); 

private:
  T& t_;
;

class LongClassName

public:
  LongClassName() : a_( *this ) 

  void pubFunc()
  
    a_.callFunc( &LongClassName::privFunc ); // Can I avoid explicitly using "LongClassName" here?
  

private:
  void privFunc()  cout << __PRETTY_FUNCTION__ << endl; 

  A<LongClassName> a_; // Can I avoid explicitly using "LongClassName" here?
;

int main( int argc, char* argv[] )

  LongClassName().pubFunc();
  return 0;

我尝试过的: 阅读Is there a __CLASS__ macro in C++?,所以我知道没有__CLASS__(伪等效于__FUNCTION__)预处理宏。该帖子的一些解决方案从__PRETTY_FUNCTION__ 中提取类名 - 但这是不适用于这种情况的运行时解决方案。

我在 *** 上阅读了 conflicting information 关于 typeid(T) 是运行时还是编译时;无论哪种方式,A&lt;typeid(*this).name()&gt; a_; 都无法编译,而且无论如何看起来都是错误的:在那种情况下显然没有 this。 根据我的阅读,https://en.cppreference.com/w/cpp/language/typeid 处的文字清楚地表明typeid 是运行时的,因此不适用于这种情况。

【问题讨论】:

您是否担心输入过多,或者您是否正在尝试解决真正的问题? @foreknownas_463035818 - 学术好奇心:能够隐式引用类名似乎“不错”/代码危害较小。 您可以使用decltype(*this),因为它在编译时运行,但正如您所说,在这种情况下没有this decltype() 可能更像您需要的,而不是 typeid() 【参考方案1】:

没有办法避免在LongClassName::privFuncA&lt;LongClassName&gt; a_; 中使用类型名称。

也就是说,您仍然可以让您的生活更轻松。您可以为LongClassName 创建一个别名,您可以在它的位置使用它。添加

using LCN = LongClassName;

将允许您使用LCN 代替LongClassName

【讨论】:

【参考方案2】:

您可以使用重新定义的默认参数声明本地别名模板,以避免在第二种情况下使用类名:

template<typename T = LongClassName> using
A = ::A<T>;
A<> a_; // Can I avoid explicitly using "LongClassName" here?

对于 LongClassName 的较短名称,有一个通用约定,即用通用名称声明相应的类型别名。它也将有助于编写复制/移动构造函数等:

class LongClassName

public:
  using Self = LongClassName;

  LongClassName() : a_( *this ) 

  LongClassName(Self const &); // copy constructor

  Self & operator =(Self const &); // copy assignment operator

  void pubFunc()
  
    a_.callFunc( &Self::privFunc ); // Can I avoid explicitly using "LongClassName" here?
  

private:
  void privFunc()  cout << __PRETTY_FUNCTION__ << endl; 

  A<Self > a_; // Can I avoid explicitly using "LongClassName" here?
;

【讨论】:

这是一种巧妙的处理方式,而且似乎是一个很好的约定——只有一个对类名的显式引用,并且在其他任何地方都易于阅读。 如果类名很短,你会使用Self吗(为了与长时的情况保持一致)?换句话说,使用Self 而不是一般的类名是一个好习惯吗? @Evg 是的,我通常总是声明这个别名。请注意,即使类名不是那么长,它也可以使用。例如,它可以使用普通搜索快速定位复制/移动构造函数或成员函数指针,并简化重构。我认为甚至有人建议为此目的在语言中添加某种内置标识符(除了this)。 也会用。谢谢!还有一个问题:公共成员类型是否有任何用例?应该是public 还是private 这不是我所说的 C++ 程序中的常见做法。我已经使用了它,具有相同的 Self 命名约定。我也使用using Super = MyBaseClass;(对象帕斯卡影响)。

以上是关于可以在编译时隐式引用类名吗?的主要内容,如果未能解决你的问题,请参考以下文章

RuntimeError: GPU:0 上的 CUDA 运行时隐式初始化失败。状态:所有支持 CUDA 的设备都忙或不可用

java 编译中文件名和类名不一致的问题

018: class, objects and instance: static method

调用 printf 时隐式转换为 char*

如何正确使用转换构造函数?

java实例化