【问题标题】: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__ 中提取类名 - 但这是不适用于这种情况的运行时解决方案。

我在 StackOverflow 上阅读了 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()

标签: c++ templates class-names


【解决方案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;(对象帕斯卡影响)。
    猜你喜欢
    • 2014-11-13
    • 1970-01-01
    • 2015-05-29
    • 2011-06-06
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    相关资源
    最近更新 更多