gpt4 book ai didi

c++ - 重载成员函数的函数特征

转载 作者:行者123 更新时间:2023-12-01 13:34:04 25 4
gpt4 key购买 nike

我具有以下有关函数特征的代码:

    template<typename T>
struct function_traits;

template<class F>
struct function_traits;

// function pointer
template<class R, class... Args>
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>
{};

template<class R, class... Args>
struct function_traits<R(Args...)>
{
using return_type = R;

static constexpr std::size_t arity = sizeof...(Args);

template <std::size_t N>
struct argument
{
static_assert(N < arity, "error: invalid parameter index.");
using type = typename std::tuple_element<N,std::tuple<Args...>>::type;
};
};

// member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&,Args...)>
{};

// const member function pointer
template<class C, class R, class... Args>
struct function_traits<R(C::*)(Args...) const> : public function_traits<R(C&,Args...)>
{};

// member object pointer
template<class C, class R>
struct function_traits<R(C::*)> : public function_traits<R(C&)>
{};
另一个具有以下签名的Matrix类:
#include <iostream>

/**
* @struct MatrixDims
* @brief Matrix dimensions container
*/
typedef struct MatrixDims
{
int rows, cols;
} MatrixDims;

/**
* Matrix class (only for 2D matrices)
*/
class Matrix
{
public:
const std::string errInvalidDims = "Error: Invalid matrices dimensions for this operation.";
const std::string errIndexOutOfRange = "Error: Index out of range.";
const std::string errFailToLoadMatrix = "Error: Failed to load elements to matrix from file.";

/**
* Matrix object constructor
* @param n Amount of rows
* @param m Amount of columns
*/
Matrix(int n, int m);

/***
* Copy Constructor for Matrix
* @param m Matrix to be copied
*/
Matrix(const Matrix &m);

/**
* default C'tor
*/
Matrix(): Matrix(1,1) {};

/***
* Destructor for Matrix
*/
~Matrix();

//########################## Operator Overloading Functions ########################################

/**
* Operator overload for = operator
* @param m Matrix to be copied
* @return reference to calling object
*/
Matrix& operator=(const Matrix &M);


/**
* Operator overload for Matrix multiplication.
* @param M: right side Matrix
* @return new matrix with new dimensions
* (Num of rows = number of rows of calling matrix, Num of Columns = num of columns as right side matrix)
*/
Matrix operator*(const Matrix &M) const;

/**
* Operator Overload for Matrix addition, on invalid
* @param M Right side Matrix
* @return new matrix with same dimension as calling matrix
*/
Matrix operator+(const Matrix &M) const;

/**
* Operator Overload for Matrix +=
* @param M Right side Matrix
* @return reference to the calling matrix after the addition
*/
Matrix& operator+=(const Matrix &M);

/**
* Overload to () operator, allows access and change of the i,j coordinate
* @param i - ith row
* @param j - jth column
* @return reference to the value stored in the i,j coordinate
*/
float& operator()(int i, int j);

/**
* Overload to () operator (const version), allows access to i,j coordinate
* @param i - ith row
* @param j - jth column
* @return reference to the value stored in the i,j coordinate
*/
const float& operator()(int i, int j) const;

/**
* Overload to the [] operator, allows access and modification of the ith Matrix value as if
* it were flattened in to a vector.
* For example: Matrix M of shape (2,3) M[5] = M(1,2) (with column and row numbers starting from 0)
* @param i-ith coordinate of the flattened vector
* @return reference to the value in the ith coordinate
*/
float& operator[](int i);

/**
* Overload to the [] operator,(const version) allows access of the ith Matrix value as if
* it were flattened in to a vector.
* For example: Matrix M of shape (2,3) M[5] = M(1,2) (with column and row numbers starting from 0)
* @param i-ith coordinate of the flattened vector
* @return reference to the value in the ith coordinate
*/
const float& operator[](int i) const;


/**
* Image Prints the calling Matrix object
* @param os
* @return reference to the os
*/
friend std::ostream& operator<<(std::ostream &os, const Matrix& M);

/**
* Input of binary data to matrix
* @param is input stream to read from
* @param M matrix to fill
* @return ref to is
*/
friend std::istream& operator>>(std::istream &is, Matrix& M);
/**
* Scalar multiplication on the right of the matrix
* @param left
* @param right
* @return
*/
Matrix operator*(const float& right);
/**
* Scalar multiplication on the left of the matrix
* @param left
* @param right
* @return
*/
friend Matrix operator*(const float& left, const Matrix& right);


/***
* getter for the number of rows
*/
int getRows() const {return rows;}

/***
* getter for the number of columns
*/
int getCols() const {return cols;}

/**
* Transforms a matrix to a column vector.
* @return ref to this
*/
Matrix& vectorize() {
rows = rows * cols;
cols = 1;
return *this;
}

/**
* Plain prints this matrix, simply prints the elemnts space separated.
*/
void plainPrint(){
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getCols(); j++){
std::cout << (*this)(i,j) << " ";
}
std::cout << std::endl;
}
}

/**
* Plain prints this matrix, simply prints the elemnts space separated. const version
*/
void plainPrint() const{
for(int i = 0; i < getRows(); i++){
for(int j = 0; j < getCols(); j++){
std::cout << (*this)(i,j) << " ";
}
std::cout << std::endl;
}
}



private:
float *matrix;
int rows, cols;

};
这是我作为TA的类(class)中C++练习的一部分。
我想尝试一下,看看我的学生是否按照我们的预期将其参数作为const引用传递了。
例如
using Traits = function_traits<decltype(&Matrix::operator=)>;
if(!std::is_same<const Matrix&, Traits::argument<1>::type>::value)
{
std::cerr << "Operator= does not accept by const reference" << std::endl;
exit(2);
}
对于没有重载的运算符,这似乎工作得很好。但是,对于像*或构造函数这样的重载运算符,我无法获得相同的测试。
这似乎是因为decltype不能区分重载的方法,但是在过去的几个小时中,我尝试了几件事,并且无法进行任何工作。
有什么建议么?
编辑*
无效的示例:
enter image description here
谢谢

最佳答案

一组重载不是一种类型。重载时,您不能decltype operator*,因为您必须先选择一个重载。正如注释中已建议的那样,可以通过static_cast完成。
这个answer解释了一个非常有用的习语,用于检查类型的属性。为了完整起见,我在此处包括以下代码:

// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf.
template <typename...>
using void_t = void;

// Primary template handles all types not supporting the operation.
template <typename, template <typename> class, typename = void_t<>>
struct detect : std::false_type {};

// Specialization recognizes/validates only types supporting the archetype.
template <typename T, template <typename> class Op>
struct detect<T, Op, void_t<Op<T>>> : std::true_type {};

它依赖于SFINAE,这不是您自己不能写的东西。但是,它将大部分样板重构为上述通用部分,剩下的就是为所需属性定义模板。对于具有所需属性的类型,该模板必须“确定”,对于不具有所需属性的类型,该模板应失败。
我决定先使用 static_cast,然后再使用 decltype。仅此一个看起来有点奇怪,但它所做的只是:当存在所需签名的 operator*时成功,否则失败:
template <typename T>
using const_ref_derefop = decltype(static_cast< T&(T::*)(const T&) >(&T::operator*));
您可以为其他运算符或其他签名编写相同的内容,其用法是:
struct A {
A& operator*(const A&);
A& operator*(A);
};
struct B {
B& operator*(B);
};

int main() {
std::cout << detect<A,const_ref_derefop>::value;
std::cout << detect<B,const_ref_derefop>::value;
}
输出:
10
关键点实际上只是将 &T::operator*转换为具有所需签名的成员函数指针。如果该签名没有重载,这将失败。

关于c++ - 重载成员函数的函数特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62514652/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com