举一个简单的CRTP例子:
template <class Target>
struct StaticCallable
{
static auto StaticCall()
{
return Target().Call();
}
using ReturnType = decltype(Target().Call());
};
struct StaticCallableInt : StaticCallable<StaticCallableInt>
{
int Call() { return 2; }
};
int main()
{
StaticCallableInt::ReturnType val;
val = StaticCallableInt::StaticCall();
}
StaticCallable<>
是用 StaticCallableInt
实例化的,此时它还不是一个完整的类型。对于StaticCall()
来说,没关系。评估被推迟到调用该函数为止,届时 StaticCallableInt
将是一个完整的类型。
对于
ReturnType
别名来说,这是一个问题,因为它是当场评估的,并且需要 StaticCallableInt
才能在那时声明 Call()
。如果这个需求没有得到满足,这段代码就无法编译。
CRTP 中的类型别名有什么好的技巧吗?我想到的一个解决方案是使用辅助类来满足所有类详细信息
StaticCallable<>
的需要:
struct CallableInt
{
int Call() { return 2; }
};
struct StaticCallableInt : StaticCallable<CallableInt> {};
是否有其他方法可以让类型别名依赖于不完整的类型,可能是通过推迟别名的评估?
您可以通过将别名放入内部结构中来添加另一个间接级别:
template <class Target>
struct StaticCallable
{
static auto StaticCall()
{
return Target().Call();
}
struct RetType
{
using value = decltype(Target().Call());
};
};
struct StaticCallableInt : StaticCallable<StaticCallableInt>
{
int Call() { return 2; }
};
int main()
{
StaticCallableInt::RetType::value val;
val = StaticCallableInt::StaticCall();
}