以下类实现CRTP。我希望类Derived
使用Base
提供的构造函数,所以我写了using
。但是,我收到错误消息,“只能从直接基类继承构造函数”。等效于成员变量x
。
template<template<typename, size_t> typename G, typename F, size_t U>
struct Base
{
double x;
Base(double x) : x{ x } {}
double gimme_x()
{
return (*static_cast<G<F, U>*>(this)).gimme_x();
}
};
template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
using Base<Derived, double, U>::Base;
using Base<Derived, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
可以通过将Base
的模板模板实现更改为仅使用常规模板来缓解此问题。
template<typename G, typename F, size_t U>
struct Base
{
double x;
Base(double x) : x{ x } {}
double gimme_x()
{
return (*static_cast<G*>(this)).gimme_x();
}
};
template<typename F, size_t U>
struct Derived : Base<Derived<F, U>, double, U>
{
using Base<Derived<F, U>, double, U>::Base;
using Base<Derived<F, U>, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
尽管第二个看起来比较冗长,但在这种情况下,它似乎应该等同于第一个。有什么区别?为什么第一个实施失败?
答案 0 :(得分:1)
避免使用injected-class-name的简单解决方法是使用全名::Derived
。
template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
using Base<::Derived, double, U>::Base;
using Base<::Derived, double, U>::x;
double gimme_x()
{
return x + 1.8;
}
};
同时使用gcc / clang Demo编译代码。
这是一个msvc错误,例如
在以下情况下,injected-class-name被视为类模板本身的模板名称:
- 后跟<< / li>
- 它用作与模板模板参数相对应的模板参数
- 它是朋友类模板声明的详细类说明符中的最终标识符。