[英]Defining conversion operator for specialized template class only
I want to define conversion to float for matrix<1, 1>. 我想为矩阵<1、1>定义为浮点型的转换。 I have trouble figuring out how to actually define it. 我很难弄清楚如何真正定义它。 If I make it a global function 如果我将其设为全局函数
template<typename T>
inline operator T(const matrix<T, 1, 1> &m){ return m(0, 0); }
I get "operator.. must be a non static member function" 我得到“运算符..必须是非静态成员函数”
I can of course define it as member for the generic matrix template but then it will be defined for all matrices - which is not what I want. 我当然可以将其定义为通用矩阵模板的成员,但随后将为所有矩阵定义它-这不是我想要的。 I want it to be defined only for the specific case of 1x1 matrix. 我希望仅针对1x1矩阵的特定情况进行定义。
You have to specialize a class for that, for example: 您必须为此专门设置一个类,例如:
template <typename Base, typename T, std::size_t W, std::size_t H>
struct MatrixConversion
{ /*Empty*/ };
template <typename Base, typename T> struct MatrixConversion<T, 1u, 1u>
{
operator const T&() const { return static_cast<const Base&>(*this).m[0][0]; }
};
template <typename T, std::size_t W, std::size_t H>
struct Matrix : MatrixConversion<Matrix<T, W, H>, T, W, H>
{
// Your code
};
composition plus specialisation would be the most maintainable approach. 组合加专业化将是最可维护的方法。
You did not specify the number of dimensions in your matrix template class, so I have assumed it can be variadic. 您没有在矩阵模板类中指定维数,因此我假设它可以是可变的。
#include <cstdint>
#include <utility>
//
// forward-declare class template for convenience.
//
template<class T, std::size_t...Dimensions>
struct matrix;
//
// classes to figure out the storage requirements of a multi-dimensional
// matrix
//
template<class T, std::size_t...Dimensions> struct storage;
template<class T, std::size_t N>
struct storage<T, N>
{
using type = T[N];
};
template<class T, std::size_t...Rest, std::size_t N>
struct storage<T, N, Rest...>
{
using less_dimension_type = typename storage<T, Rest...>::type;
using type = less_dimension_type[N];
};
//
// functions for dereferencing multi-dimensional arrays
//
template<class Array, class Arg>
decltype(auto) deref(Array& array, Arg&& arg)
{
return array[arg];
}
template<class Array, class Arg, class Arg2>
decltype(auto) deref(Array& array, Arg&& arg, Arg2&& arg2)
{
return array[arg][arg2];
}
template<class Array, class Arg, class...Args>
decltype(auto) deref(Array& array, Arg&& arg, Args&&...args)
{
return deref(deref(array, arg), std::forward<Args>(args)...);
}
//
// prototype for operations we want to conditionally apply
//
template<class Matrix>
struct matrix_conditional_ops
{
// in the general case, none
};
//
// compose the matrix class from conditional_ops<>
//
template<class T, std::size_t...Dimensions>
struct matrix
: matrix_conditional_ops<matrix<T, Dimensions...>>
{
template<class...Dims>
decltype(auto) at(Dims&&...ds)
{
return deref(_data, std::forward<Dims>(ds)...);
}
template<class...Dims>
decltype(auto) at(Dims&&...ds) const
{
return deref(_data, std::forward<Dims>(ds)...);
}
typename storage<T, Dimensions...>::type _data;
};
//
// define the condition operations for the <T, 1, 1> case
//
template<class T>
struct matrix_conditional_ops<matrix<T, 1, 1>>
{
using matrix_type = matrix<T, 1, 1>;
operator T const() { return static_cast<matrix_type const&>(*this).at(0,0); }
};
int main()
{
matrix<double, 1, 1> m11;
m11.at(0,0) = 6.0;
double d = m11;
matrix<double, 2, 2> m22;
// compile error:
// double d2 = m22;
// bonus points:
matrix<double, 3, 5, 2, 7> mxx;
mxx.at(2, 4, 1, 6) = 4.3; // probably needs some compile-time checking...
}
someone may want to check my logic for the array packing/dereferencing... 有人可能想检查一下我的逻辑以进行数组打包/解引用...
Jarod and Richard already gave you the best answers in my opinion, they scale well to any number of operators with all kinds of restrictions. 我认为Jarod和Richard已经为您提供了最佳答案,它们可以很好地扩展到具有各种限制的任何数量的运营商。
However, if you cannot afford to redesign your class, or all you need is a quick and dirty opertor T()
you can get away with the following 但是,如果您无力重新设计课程,或者您只需要一个快速而肮脏的opertor T()
,则opertor T()
以下问题:
template<typename T, std::size_t N1, std::size_t N2>
struct Matrix
{
T m[N1][N1];
operator T()
{
static_assert(N1 == 1 && N2 == 1, "Only applicable to scalars");
return m[0][0];
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.