我在类层次结构中有一些概念性问题,其中Base类依赖于固定的标量类型T
,但派生的CRTP类使用返回值类型推导。
例如,请考虑以下类层次结构:
template<typename ... Args> struct VectorBase;
template<typename T>
struct VectorBase<T>
{
virtual T eval(int) const = 0;
auto operator[](int i) {return this->eval(i);}
};
template<typename T, typename Derived>
struct VectorBase<T, Derived> : public VectorBase<T>
{
virtual T eval(int i) const override final { return this->operator[](i); }
auto operator[](int i) const
{
return static_cast<Derived const&>(*this).operator[](i);
}
};
template<typename T>
struct Vector : public VectorBase<T, Vector<T> >
{
//just for code shortness,
//in reality there is a container which returns the corresponding elements
auto operator[](int i) const { return T{}; }
};
template<typename VectorType>
struct SomeTransformation : public VectorBase< /* ... what to write here generically? */ double, SomeTransformation<VectorType> >
{
VectorType const& v;
SomeTransformation(VectorType const& _v) : v(_v) {}
auto operator[](int i) const
{
//do something with vector v and return i-th element, e.g.
return v[i]*0.1;
}
};
现在,给定值类型为int
的特定向量,例如,可以应用SomeTransformation
并获取值类型为double
的向量。此外,我可以确定SomeTransformation
派生自VectorBase<double>
,因此,例如,我不能错误地将其分配给VectorBase<int>
指针:
int main()
{
Vector<int> v;
std::cout<<typeid(decltype(v[0])).name()<<std::endl; //prints "i" for int
auto u = SomeTransformation<decltype(v)>(v);
std::cout<<typeid(decltype(u[0])).name()<<std::endl; //prints "d" for double
//works
std::unique_ptr<VectorBase<double> > ud = std::make_unique<SomeTransformation<decltype(v)> >(v);
//gives a compile-time error, which is good
//std::unique_ptr<VectorBase<int> > ui = std::make_unique<SomeTransformation<decltype(v)> >(v);
}
现在问题出现了:在SomeTransformation
的标量类型参数中,我写了/* ... what to write here generically? */
,我真的想写一些像
template<typename VectorType>
struct SomeTransformation :
public VectorBase<decltype(std::declval<SomeTransformation<VectorType> >().operator[](0)), SomeTransformation<VectorType> >
{
//...
};
为了自动推导转换的值类型并将此类型传播到基类。但是,这似乎不起作用,我认为是因为基类在派生类之前被实例化...所以我想推断出类型的类还不存在。
有没有办法在不破坏继承层次结构的情况下获取此行为?
答案 0 :(得分:0)
我自己想出了一个可能的替代方案,并希望将其提交讨论。
例如,可以向派生类添加类型参数T
,然后使用虚拟类型以便实例化此类一次。有了这个,就可以推导出如此创建的类的返回类型,它将在下一步中用于实例化实际使用的类。
示例:
namespace detail
{
template<typename T, typename VectorType>
struct SomeTransformation :
public VectorBase<T, SomeTransformation<T, VectorType> >
{
//the same as above
};
}
struct DummyType
{
//make any type convertible to DummyType
template<typename T> DummyType(T const&) {}
};
template<typename VectorType>
using SomeTransformationValueType =
decltype(std::declval<detail::SomeTransformation<DummyType, VectorType> >().operator[](0));
template<typename VectorType>
using SomeTransformation =
typename detail::SomeTransformation<SomeTransformationValueType<VectorType>, VectorType>;