На имя класса можно ссылаться неявно во время компиляции? - PullRequest
5 голосов
/ 07 ноября 2019

Есть ли способ неявной ссылки на имя класса во время компиляции?

В частности, если я хочу объявить экземпляр template class A, используя class B изнутриобласть действия class B, есть ли способ избежать явной ссылки на "B" в синтаксисе для объявления экземпляра class A?

Для лучшей иллюстрации на примере:

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

То, что я пробовал:
Чтение Есть ли макрос в C ++ в C ++? , поэтому я знаю, что макроса препроцессора __CLASS__ (псевдоэквивалентного __FUNCTION__) нет. Некоторые решения этого поста извлекают имя класса из __PRETTY_FUNCTION__, но это решение времени выполнения, неприменимо к этой ситуации.

Я прочитал конфликтующие информацию в StackOverflow о том, является ли typeid(T) временем выполнения или временем компиляции;в любом случае, A<typeid(*this).name()> a_; не компилируется и выглядит неправильно в любом случае: в этом контексте явно нет this.
Насколько я понимаю, текст https://en.cppreference.com/w/cpp/language/typeid ясно указывает на то, что typeid - это среда выполненияи так неприменимо к данной ситуации.

Ответы [ 2 ]

8 голосов
/ 07 ноября 2019

Нет способа избежать использования имени типа в LongClassName::privFunc и A<LongClassName> a_;.

Тем не менее, вы все равно можете сделать свою жизнь проще. Вы можете сделать псевдоним для LongClassName, чтобы вы могли использовать его вместо него. Добавление

using LCN = LongClassName;

позволит вам использовать LCN вместо LongClassName

4 голосов
/ 07 ноября 2019

Вы можете объявить шаблон локального псевдонима с переопределенным параметром по умолчанию, чтобы избежать использования имени класса во втором случае:

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