我有 Vector ( CVector<T, std::size_t Size>
)、Matrix ( CMatrix<T, std::size_t Height, std::size_t Width>
) 和 Tensor ( CTensor<T, std::size_t... Sizes>
) 类,我希望能够从 CTensor
隐式转换类到 CVector
如果 sizeof...(Sizes) == 1
类和 CMatrix
如果 sizeof...(Sizes) == 2
类,所以我有以下转换运算符(最初我没有 std::enable_if
模板参数希望我可以使用 SFINAE 来防止它编译):
template <typename std::enable_if<sizeof...(Sizes) == 2, int>::type = 0>
operator CMatrix<NumType, Sizes...>() const
{
static_assert(sizeof...(Sizes) == 2, "You can only convert a rank 2 tensor to a matrix");
CMatrix<NumType, Sizes...> matResult;
auto& arrThis = m_numArray;
auto& arrResult = matResult.m_numArray;
concurrency::parallel_for_each( arrResult.extent, [=, &arrThis, &arrResult]( concurrency::index<2> index ) restrict( amp ) {
arrResult[index] = arrThis[index];
} );
return matResult;
}
template <typename std::enable_if<sizeof...(Sizes) == 1, int>::type = 0>
operator CVector<NumType, Sizes...>() const
{
static_assert(sizeof...(Sizes) == 1, "You can only convert a rank 1 tensor to a vector");
CVector<NumType, Sizes...> vecResult;
auto& arrThis = m_numArray;
auto& arrResult = vecResult.m_numArray;
concurrency::parallel_for_each( arrResult.extent, [=, &arrThis, &arrResult]( concurrency::index<1> index ) restrict( amp ) {
arrResult[index] = arrThis[index];
} );
return vecResult;
}
但是,如果我实例化 CTensor<float, 3, 3, 3>
例如,尝试编译时,我会收到错误消息,声明 CMatrix
的模板参数过多。和 CVector
以及有关 std::enable_if<false, int>
类型缺失的错误.有没有一种方法可以实现这些运算符而无需专门化 CTensor
对于排名 1 和 2?
最佳答案
我已经简化了之前的解决方案,详情如下。
根本不需要 SFINAE,因为模板方法中有 static_assert
,它仅在使用时实例化。
我的解决方案使转换运算符成为具有相关参数 的模板方法(以便编译器不实例化其主体,仅解析签名),并添加 -1
大小假装在大小为 1 的张量内缺少维度(不是张量本身,而是提取参数包的辅助类),以允许编译器实例化张量模板本身,但不允许稍后实例化张量内的转换运算符无效维度。
#include <cstddef>
template <typename T, unsigned int index, T In, T... args>
struct GetArg
{
static const T value = GetArg<T, index-1, args...>::value;
};
template <typename T, T In, T... args>
struct GetArg<T, 0, In, args...>
{
static const T value = In;
};
template <typename T, T In>
struct GetArg<T, 1, In>
{
static const T value = -1;
};
template <typename T, std::size_t Size>
struct CVector
{
};
template <typename T, std::size_t Height, std::size_t Width>
struct CMatrix
{
};
template <typename T, std::size_t... Sizes>
struct CTensor
{
template <std::size_t SZ = sizeof...(Sizes)>
operator CVector<T, GetArg<std::size_t, 0, Sizes...>::value>() const
{
static_assert(SZ == 1, "You can only convert a rank 1 tensor to a vector");
CVector<T, Sizes...> vecResult;
return vecResult;
}
template <std::size_t SZ = sizeof...(Sizes)>
operator CMatrix<T, GetArg<std::size_t, 0, Sizes...>::value, GetArg<std::size_t, 1, Sizes...>::value>() const
{
static_assert(SZ == 2, "You can only convert a rank 2 tensor to a matrix");
CMatrix<T, Sizes...> matResult;
return matResult;
}
};
int main()
{
CTensor<float, 3> tensor3;
CTensor<float, 3, 3> tensor3_3;
CTensor<float, 3, 3, 3> tensor3_3_3;
CVector<float, 3> vec(tensor3);
//CVector<float, 3> vec2(tensor3_3); // static_assert fails!
CMatrix<float, 3, 3> mat(tensor3_3);
//CMatrix<float, 3, 3> mat2(tensor3_3_3); // static_assert fails!
}
关于c++ - 除非满足静态条件,否则阻止转换运算符编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25584540/