项目结构如下:
greenNoiseMask 是原有项目
在解决方案中添加google test 项目:sample-test2
gtest基础使用02:测试已有项目中的类和函数
头文件:
#pragma once
#include
template <typename T>
class Matrix {
private:
std::vector<std::vector<T>> matrix;
int m_nRows;
int m_nCols;
public:
// 构造函数
Matrix(int m_nRows, int m_nCols, const T& initial = T());
// 获取矩阵的行数和列数
int numRows() const;
int numCols() const;
// 获取矩阵中特定位置的元素
T& at(int row, int col);
// 获取矩阵元素的值
T get(int row, int col) const;
// 更新矩阵元素的值
void set(int row, int col, const T& value);
// 矩阵加法
Matrix<T> operator+(const Matrix<T>& other) const;
// 矩阵减法
Matrix<T> operator-(const Matrix<T>& other) const;
// 矩阵乘法
Matrix<T> operator*(const Matrix<T>& other) const;
// 统计矩阵中某个值的数量
int countValue(const T& value) const;
};
// 矩阵加法 多线程
template <typename T>
Matrix<T> parallelMatrixAddition(const Matrix<T>& m1, const Matrix<T>& m2);
// 矩阵减法多线程
template <typename T>
Matrix<T> parallelMatrixSubtraction(const Matrix<T>& m1, const Matrix<T>& m2);
// 矩阵减法 多线程
template <typename T>
Matrix<T> parallelMatrixMultiply(const Matrix<T>& m1, const Matrix<T>& m2);
实现
#include "Matrix.h"
#include
#include
#include
template class Matrix<int>;
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template int Matrix<int>::numRows() const;
template int Matrix<int>::numCols() const;
template int& Matrix<int>::at(int row, int col);
template int Matrix<int>::get(int row, int col) const;
template void Matrix<int>::set(int row, int col, const int& value);
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator-(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator*(const Matrix<int>& other) const;
template int Matrix<int>::countValue(const int& value) const;
template Matrix<int> parallelMatrixAddition(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixSubtraction(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixMultiply(const Matrix<int>& m1, const Matrix<int>& m2);
template <typename T>
Matrix<T>::Matrix(int m_nRows, int m_nCols, const T& initial) : m_nRows(m_nRows), m_nCols(m_nCols), matrix(m_nRows, std::vector<T>(m_nCols, initial))
{}
template <typename T>
int Matrix<T>::numRows() const
{
return m_nRows;
}
template <typename T>
int Matrix<T>::numCols() const
{
return m_nCols;
}
// 获取矩阵中特定位置的元素
template <typename T>
T& Matrix<T>::at(int row, int col)
{
if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols)
{
throw std::out_of_range("Invalid matrix index");
}
return matrix[row][col];
}
// 获取矩阵元素的值
template <typename T>
T Matrix<T>::get(int row, int col) const
{
if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols)
{
throw std::out_of_range("Invalid matrix index");
}
return matrix[row][col];
}
// 更新矩阵元素的值
template <typename T>
void Matrix<T>::set(int row, int col, const T& value) {
if (row < 0 || row >= m_nRows || col < 0 || col >= m_nCols) {
throw std::out_of_range("Invalid matrix index");
}
matrix[row][col] = value;
}
// 矩阵加法
template <typename T>
Matrix<T> Matrix<T>::operator+(const Matrix<T>& other) const
{
if (m_nRows != other.m_nRows || m_nCols != other.m_nCols)
{
throw std::invalid_argument("Matrix dimensions don't match for addition");
}
Matrix<T> result(m_nRows, m_nCols);
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j)
{
result.matrix[i][j] = matrix[i][j] + other.get(i, j);
}
}
return result;
}
// 矩阵减法
template <typename T>
Matrix<T> Matrix<T>::operator-(const Matrix<T>& other) const
{
if (m_nRows != other.m_nRows || m_nCols != other.m_nCols)
{
throw std::invalid_argument("Matrix dimensions don't match for subtraction");
}
Matrix<T> result(m_nRows, m_nCols);
for (int i = 0; i < m_nRows; ++i)
{
for (int j = 0; j < m_nCols; ++j) {
result.matrix[i][j] = matrix[i][j] - other.get(i,j);// other.matrix[i][j];
}
}
return result;
}
// 矩阵乘法
template <typename T>
Matrix<T> Matrix<T>::operator*(const Matrix<T>& other) const
{
if (m_nCols != other.m_nRows)
{
throw std::invalid_argument("Matrix dimensions are not compatible for multiplication");
}
int resultRows = m_nRows;
int resultCols = other.m_nCols;
Matrix<T> result(resultRows, resultCols);
for (int i = 0; i < resultRows; ++i)
{
for (int j = 0; j < resultCols; ++j)
{
result.matrix[i][j] = static_cast<T>(0);
for (int k = 0; k < m_nCols; ++k)
{
result.matrix[i][j] += matrix[i][k] * other.get(k, j);
}
}
}
return result;
}
// 统计矩阵中某个值的数量
template <typename T>
int Matrix<T>::countValue(const T& value) const
{
int count = 0;
for (int i = 0; i < m_nRows; ++i) {
for (int j = 0; j < m_nCols; ++j) {
if (matrix[i][j] == value) {
count++;
}
}
}
return count;
}
template <typename T>
Matrix<T> parallelMatrixAddition(const Matrix<T>& m1, const Matrix<T>& m2)
{
if (m1.numRows() != m2.numRows() || m1.numCols() != m2.numCols())
{
throw std::invalid_argument("Matrix dimensions don't match for addition");
}
Matrix<T> result(m1.numRows(), m1.numCols());
std::vector<std::thread> threads;
const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
const int rowsPerThread = (m1.numRows() + numThreads - 1) / numThreads; // Rows per thread
for (int i = 0; i < numThreads; ++i)
{
threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
{
for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
{
for (int col = 0; col < result.numCols(); ++col)
{
result.at(row, col) = m1.get(row, col) + m2.get(row, col);
}
}
});
}
for (auto& thread : threads)
{
thread.join();
}
return result;
}
template <typename T>
Matrix<T> parallelMatrixSubtraction(const Matrix<T>& m1, const Matrix<T>& m2)
{
if (m1.numRows() != m2.numRows() || m1.numCols() != m2.numCols())
{
throw std::invalid_argument("Matrix dimensions don't match for subtraction");
}
Matrix<T> result(m1.numRows(), m1.numCols());
std::vector<std::thread> threads;
const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
const int rowsPerThread = (m1.numRows() + numThreads - 1) / numThreads; // Rows per thread
for (int i = 0; i < numThreads; ++i)
{
threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
{
for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
{
for (int col = 0; col < result.numCols(); ++col)
{
result.at(row, col) = m1.get(row, col) - m2.get(row, col);
}
}
});
}
for (auto& thread : threads)
{
thread.join();
}
return result;
}
template <typename T>
Matrix<T> parallelMatrixMultiply(const Matrix<T>& m1, const Matrix<T>& m2)
{
if (m1.numCols() != m2.numRows())
{
throw std::invalid_argument("Matrix dimensions are not compatible for multiplication");
}
int resultRows = m1.numRows();
int resultCols = m2.numCols();
Matrix<T> result(resultRows, resultCols);
std::vector<std::thread> threads;
//std::mutex mutex; // Mutex to control access to the result matrix
const int numThreads = std::thread::hardware_concurrency(); // Number of available threads
const int rowsPerThread = (resultRows + numThreads - 1) / numThreads; // Rows per thread
for (int i = 0; i < numThreads; ++i) {
threads.emplace_back([&m1, &m2, &result, i, rowsPerThread]()
{
for (int row = i * rowsPerThread; row < std::min((i + 1) * rowsPerThread, result.numRows()); ++row)
{
for (int col = 0; col < result.numCols(); ++col)
{
T sum = static_cast<T>(0);
for (int k = 0; k < m1.numCols(); ++k)
{
sum += m1.get(row, k) * m2.get(k, col);
}
//std::lock_guard lock(mutex);
result.set(row, col, sum);
}
}
});
}
for (auto& thread : threads)
{
thread.join();
}
return result;
}
#include "pch.h"
#include "..\greenNoiseMask\Matrix.h"
// 测试构造函数和矩阵元素访问
TEST(MatrixTest, ConstructionAndAccess) {
// 创建一个矩阵
Matrix<int> mat(2, 2);
// 测试矩阵是否被正确构建
EXPECT_EQ(mat.numRows(), 2);
EXPECT_EQ(mat.numCols(), 2);
// 测试矩阵元素访问
mat.at(0, 0) = 5;
mat.at(1, 1) = 10;
EXPECT_EQ(mat.at(0, 0), 5);
EXPECT_EQ(mat.at(1, 1), 10);
// 测试矩阵元素更新
mat.set(0, 0, 2) ;
mat.set(1, 1,6) ;
}
// 测试矩阵加法
TEST(MatrixTest, Addition) {
// 创建两个矩阵
Matrix<int> mat1(2, 2);
Matrix<int> mat2(2, 2);
// 设置矩阵元素
mat1.at(0, 0) = 1;
mat1.at(0, 1) = 2;
mat1.at(1, 0) = 3;
mat1.at(1, 1) = 4;
mat2.at(0, 0) = 5;
mat2.at(0, 1) = 6;
mat2.at(1, 0) = 7;
mat2.at(1, 1) = 8;
// 执行加法操作
Matrix<int> result = mat1 + mat2;
// 检查加法结果是否正确
EXPECT_EQ(result.at(0, 0), 6);
EXPECT_EQ(result.at(0, 1), 8);
EXPECT_EQ(result.at(1, 0), 10);
EXPECT_EQ(result.at(1, 1), 12);
}
// 测试矩阵加法
TEST(MatrixTest, parallelAddition) {
// 创建两个矩阵
Matrix<int> mat1(10, 10);
Matrix<int> mat2(10, 10);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
mat1.at(i, j) = i + j;
mat2.at(i, j) = -(i + j);
}
}
// 执行加法操作
Matrix<int> result = parallelMatrixAddition<int>(mat1, mat2);
// 检查加法结果是否正确
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
EXPECT_EQ(result.at(i, j), 0);
}
}
}
// 测试矩阵减法
TEST(MatrixTest, subtraction) {
// 创建两个矩阵
Matrix<int> mat1(2, 2);
Matrix<int> mat2(2, 2);
// 设置矩阵元素
mat1.at(0, 0) = 1;
mat1.at(0, 1) = 2;
mat1.at(1, 0) = 3;
mat1.at(1, 1) = 4;
mat2.at(0, 0) = 5;
mat2.at(0, 1) = 6;
mat2.at(1, 0) = 7;
mat2.at(1, 1) = 8;
// 执行减法操作
Matrix<int> result = mat1 - mat2;
// 检查减法结果是否正确
EXPECT_EQ(result.at(0, 0), -4);
EXPECT_EQ(result.at(0, 1), -4);
EXPECT_EQ(result.at(1, 0), -4);
EXPECT_EQ(result.at(1, 1), -4);
}
TEST(MatrixTest, parallelSubtraction) {
// 创建两个矩阵
Matrix<int> mat1(10, 10);
Matrix<int> mat2(10, 10);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
mat1.at(i, j) = i + j;
mat2.at(i, j) = (i + j);
}
}
// 执行减法操作
Matrix<int> result = parallelMatrixSubtraction<int>(mat1, mat2);
// 检查减法结果是否正确
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
EXPECT_EQ(result.at(i, j), 0);
}
}
}
// 测试矩阵乘法
TEST(MatrixTest, multiplication) {
// 创建两个矩阵
Matrix<int> mat1(2, 2);
Matrix<int> mat2(2, 2);
// 设置矩阵元素
mat1.at(0, 0) = 1;
mat1.at(0, 1) = 2;
mat1.at(1, 0) = 3;
mat1.at(1, 1) = 4;
mat2.at(0, 0) = 5;
mat2.at(0, 1) = 6;
mat2.at(1, 0) = 7;
mat2.at(1, 1) = 8;
// 执行乘法操作
Matrix<int> result = mat1 * mat2;
// 检查乘法结果是否正确
EXPECT_EQ(result.at(0, 0), 19);
EXPECT_EQ(result.at(0, 1), 22);
EXPECT_EQ(result.at(1, 0), 43);
EXPECT_EQ(result.at(1, 1), 50);
}
TEST(MatrixTest, parallelMatrixMultiply) {
// 创建两个矩阵
Matrix<int> mat1(10, 10);
Matrix<int> mat2(10, 10);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
mat1.at(i, j) = i + j;
if (i == j)
{
mat2.at(i, j) = 1;
}
else
{
mat2.at(i, j) = 0;
}
}
}
// 执行减法操作
Matrix<int> result = parallelMatrixMultiply<int>(mat1, mat2);
// 检查减法结果是否正确
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
EXPECT_EQ(result.at(i, j), i+j);
}
}
}
int main(int argc, char** argv) {
printf("Running main() from %s\n", __FILE__);
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
因为测试文件中使用了 Matrix 实例化,但是在自己的项目中 没有加
template class Matrix<int>;
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template int Matrix<int>::numRows() const;
template int Matrix<int>::numCols() const;
template int& Matrix<int>::at(int row, int col);
template int Matrix<int>::get(int row, int col) const;
template void Matrix<int>::set(int row, int col, const int& value);
template Matrix<int> Matrix<int>::operator+(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator-(const Matrix<int>& other) const;
template Matrix<int> Matrix<int>::operator*(const Matrix<int>& other) const;
template int Matrix<int>::countValue(const int& value) const;
template Matrix<int> parallelMatrixAddition(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixSubtraction(const Matrix<int>& m1, const Matrix<int>& m2);
template Matrix<int> parallelMatrixMultiply(const Matrix<int>& m1, const Matrix<int>& m2);
导致 google test 一直报错:VS “error LNK2019: 无法解析的外部符号 …”
参考
【C++】模板(template)进阶
因为模板需要编译两次:
如果没有加上面的实例化的模板,编译器链接的时候 不知道有Matrix 会报错
所以需要在自己的项目中 实例化要用的模板类,生成的lib 在Google test项目中才能使用