Is there a way to implicitly reference a class' name at compile-time?
Specifically, if I want to declare an instance of template class A
using class B
from within the scope of class B
, is there a way to avoid explicit reference to "B" in the syntax to declare the class A
instance?
To better-illustrate with an example:
// 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;
}
What I've tried:
Read Is there a __CLASS__ macro in C++?, so I'm aware there's no __CLASS__
(pseudo-equivalent to __FUNCTION__
) preprocessor macro. Some of the solutions to that post extract the class name from __PRETTY_FUNCTION__
- but that is a runtime solution not applicable to this situation.
I've read conflicting information on StackOverflow about whether typeid(T)
is run time or compile time; either way, A<typeid(*this).name()> a_;
doesn't compile, and looks wrong anyhow: there's obviously no this
in that context.
By my reading, the text at https://en.cppreference.com/w/cpp/language/typeid makes clear that typeid
is runtime, and so not-applicable to this situation.
There is no way to avoid using the type name in LongClassName::privFunc
and A<LongClassName> a_;
.
That said, you can still make your life easier. You can make an alias for LongClassName
that you can use it it's place. Adding
using LCN = LongClassName;
will let you use LCN
in place of LongClassName
You can declare local alias template with redefined default parameter to avoid using class name in second case:
template<typename T = LongClassName> using
A = ::A<T>;
A<> a_; // Can I avoid explicitly using "LongClassName" here?
As for shorter name for LongClassName, there is a common convention to declare corresponding type alias with a common name. It will also be helpful for writing copy / move constructors, etc:
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?
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With