如何解决区分静态数组,指针和结构的C ++模板
目前,我有一个模板函数,编译器可以推导出TI
用作静态数组和(普通类型的)指针作为参数:
template<typename TI,typename TO>
inline void foo(const TI a[4],TO b[][3]) { /* works for static arrays and pointers */ }
但是,现在我需要具有4个成员x
,y
,z
和w
的结构类型具有相同的功能,分别代表旧的数组类型。
但是我不能这样做:
template<typename TI,TO b[][3]) { /* static arrays and pointer */ }
template<typename TI,typename TO>
inline void foo(const TI a,TO b[][3]) { /* structs */ }
如果我为第一个函数指定了额外的参数size
,则指针参数最终出现在函数下方,并且由于指针没有必需的结构成员,因此编译器会引发错误。
我不能专门研究特定类型的结构,因为我们现在使用几种类型(各种内部成员类型的double
,float
,int
等)
MRE:
#include <cassert>
#include <iostream>
template <typename TI,typename TO>
inline
void foo(const TI q[4],TO a[][3])
{
std::cout << "Method 1\n";
a[0][0] = a[0][1] = a[0][2] = q[0] + q[1];
a[1][0] = a[1][1] = a[1][2] = q[1] + q[2];
a[2][0] = a[2][1] = a[2][2] = q[2] + q[3];
}
template <class QT,typename TO>
inline
void foo(const QT q,TO a[][3])
{
std::cout << "Method 2\n";
a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
}
typedef struct {
float x,y,z,w;
} float4;
int main() {
float q1[4] = {1,2,3,4};
float4 q2 = {1,4};
float *q3 = new float[4];
q3[0] = 1; q3[1] = 2; q3[2] = 3; q3[3] = 4;
float a[3][3],b[3][3],c[3][3];
foo(q1,a);
foo(q2,b);
foo(q3,c);
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
{
assert(a[i][j] == b[i][j]);
assert(b[i][j] == c[i][j]);
}
}
编译器错误:
teste.cpp:19:36: error: member reference base type 'float *const' is not a structure or
union
a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
~^~
teste.cpp:37:5: note: in instantiation of function template specialization
'foo<float *,float>' requested here
foo(q1,a);
^
teste.cpp:20:36: error: member reference base type 'float *const' is not a structure or
union
a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
~^~
teste.cpp:21:36: error: member reference base type 'float *const' is not a structure or
union
a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
~^~
3 errors generated.
解决方法
您可以做的是使用C ++ 11中提供的类型特征
您可以声明您的函数专用于以下结构:
#include <type_traits>
template <class QT,typename TO,std::enable_if_t<std::is_class<QT>::value,int> = 0>
inline
void foo(const QT q,TO a[][3])
{
std::cout << "Method 2\n";
a[0][0] = a[0][1] = a[0][2] = q.x + q.y;
a[1][0] = a[1][1] = a[1][2] = q.y + q.z;
a[2][0] = a[2][1] = a[2][2] = q.z + q.w;
}
这将使编译器为结构和类选择此模板,而不为其他模板。这就是所谓的SFINAE技术。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。