如何解决可变参数模板模板
| 我正在尝试创建一个基类,该基类是std :: array的包装器,它使一堆常见的算术运算符过载。最终结果将类似于std :: valarray,但具有静态大小。之所以这样做,是因为我正在为我的库创建大量的子类,最终复制了此功能。例如,我需要创建一个MyPixel类和一个MyPoint类,它们实际上都是可以执行算术的静态大小的数组。 我的解决方案是创建一个MyPoint和MyPixel可以派生的StaticValArray基类。但是,为了禁止用户将MyPoint添加到MyPixel,我使用CRTP模式,如下所示:template<class T1,class T2>
struct promote
{
typedef T1 type; // Assume there is a useful type promotion mechanism here
};
template<class T,size_t S,template<typename... A> class ChildClass>
class StaticValArray : public std::array<T,S>
{
public:
// Assume there are some conversion,etc. constructors here...
template<class U>
StaticValArray<typename promote<T,U>::type,S,ChildClass> operator+
(StaticValArray<U,ChildClass> const & rhs)
{
StaticValArray<typename promote<T,ChildClass> ret = *this;
std::transform(this->begin(),this->end(),rhs.begin(),ret.begin(),std::plus<typename promote<T,U>::type>());
return ret;
}
// More operators....
};
这很酷,因为ChildClass可以具有任何任意的类模板参数,并且此功能可以工作。例如:
template<class T,class U>
class MyClassTwoTypes : public StaticValArray<T,3,MyClassTwoTypes>
{ };
template<class T,class U>
class MyClassTwoTypes2 : public StaticValArray<T,MyClassTwoTypes2>
{ };
int main()
{
MyClassTwoTypes<int,float> p;
MyClassTwoTypes<double,char> q;
auto z = p + q;
MyClassTwoTypes2<double,char> r;
// r += q; // <-- Great! This correctly won\'t compile
return 0;
}
我的问题是:我想将一些ChildClass填充到StaticValArray的CRTP位中,该位不一定只将类作为其模板参数。例如,考虑以下N维点类:
template<class T,size_t S>
class MyPointND : public StaticValArray<T,MyPointND>
{ };
不幸的是,由于size_t不是类型名,因此无法编译-我收到编译器错误:
type/value mismatch at argument 3 in template parameter list for ‘template<class T,long unsigned int S,template<class ... A> class ChildClass> class StaticValArray’
test.C:36:54: error: expected a template of type ‘template<class ... A> class ChildClass’,got ‘template<class T,long unsigned int S> class MyPointND’
有什么方法可以创建一个可变参数模板模板参数包,该参数包绝对可以是任何东西(类型名,整数,size_t \,双精度数,等等?),因为最后我真的不在乎其中的类型。请注意,我不能完全指定ChildClass(例如class MyPointND: public StaticValArray<T,MyPointND<T,S>>
),因为这会破坏我的类型提升机制。
解决方法
如果您使用了std :: integral_constant代替size_t怎么办?您将在其中嵌入数组大小的数值,并且可以将其用作类型。
编辑
为了减少冗长,您可以定义自己的整数常量类,例如:
template <std::size_t N>
struct size_ : std::integral_constant<std::size_t,N> {};
然后,您可以像这样使用它:
MyPointND<int,size_<3>> x;
,您需要做的是创建一个traits
类,该类专门针对每种类型,其中包含进行类型提升所需的内容,然后将完整的类型传递给StaticValArray。
此外,使用decltype
,您不需要像这样的东西-decltype
会告诉您通过添加浮点数和整数可以得到什么。
template<class U>
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),S,ChildClass> operator+
(StaticValArray<U,ChildClass> const & rhs)
{
StaticValArray<decltype(*(T*)nullptr + *(U*)nullptr),ChildClass> ret = *this;
std::transform(this->begin(),this->end(),rhs.begin(),ret.begin(),std::plus<decltype(*(T*)nullptr + *(U*)nullptr)>());
return ret;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。