可以在编译时隐式引用类名吗?
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<typeid(*this).name()> a_;
都无法编译,而且无论如何看起来都是错误的:在那种情况下显然没有 this
。
根据我的阅读,https://en.cppreference.com/w/cpp/language/typeid 处的文字清楚地表明typeid
是运行时的,因此不适用于这种情况。
【问题讨论】:
您是否担心输入过多,或者您是否正在尝试解决真正的问题? @foreknownas_463035818 - 学术好奇心:能够隐式引用类名似乎“不错”/代码危害较小。 您可以使用decltype(*this)
,因为它在编译时运行,但正如您所说,在这种情况下没有this
decltype()
可能更像您需要的,而不是 typeid()
。
【参考方案1】:
没有办法避免在LongClassName::privFunc
和A<LongClassName> 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 的设备都忙或不可用