In modern C++ you can create arrays by three primary methods shown below.
// Traditional method
int array_one[] = {1, 2, 3, 4}
// Vector container
std::vector<int> array_two = {1, 2, 3, 4}
// array container
std::array<int, 4> array_three = {1, 2, 3, 4}
While each array method contains the same data, they are inherently different containers. I am writing a very simple Unit Test class with template functions to make it easier to pass multiple data types. I have an example shown below for the .hpp
and .cpp
calling file. The one method shown in the file takes a std::vector
and compares it to another std::vector
indice by indice to ensure that each value is within a certain tolerance of the other.
// main.cpp
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include "unit_test.hpp"
int main(int argc, const char * argv[]) {
int array_one[] = {1, 2, 3, 4};
std::vector<int> array_two = {1, 2, 3, 4};
std::vector<float> array_four = {0.99, 1.99, 2.99, 3.99};
std::array<int, 4> array_three {1, 2, 3, 4};
std::string c ("Vector Test");
UnitTest q;
double unc = 0.1;
q.vectors_are_close(array_two, array_four, unc, c);
return 0;
}
and
#ifndef unit_test_hpp
#define unit_test_hpp
#endif /* unit_test_hpp */
#include <string>
#include <typeinfo>
#include <iostream>
#include <cmath>
class UnitTest
{
public:
template <class type1, class type2>
void vectors_are_close(const std::vector<type1> &i, const std::vector<type2> &j,
double k, std::string str);
private:
template <class type1, class type2>
void is_close(type1 &i, type2 &j, double k);
};
template <class type1, class type2>
void UnitTest::vectors_are_close(const std::vector<type1> &i, const std::vector<type2> &j,
double k, std::string str)
{
unsigned long remain;
remain = 50 - str.length();
if (i.size() != j.size()) {
std::cout << str + std::string(remain, '.') +
std::string("FAILED") << std::endl;
}
else {
try {
for (int a = 0; a < i.size(); a++){
is_close(i[a], j[a], k);
}
std::cout << str + std::string(remain, '.') +
std::string("PASSED") << std::endl;
} catch (const char* msg) {
std::cout << str + std::string(remain, '.') +
std::string("FAILED") << std::endl;
}
}
}
template <class type1, class type2>
void UnitTest::is_close(type1 &i, type2 &j, double k)
{
double percent_diff = abs((j - i) / ((i + j) / 2.0));
if (percent_diff > k) {
throw "Number not in Tolerance";
}
}
In this example the code compares two vectors; however, if I want to compare std::array
containers I will have to crate a whole new function to do that, and if I want to compare two generic arrays, I will have to yet again create another function to do that. In addition, if I want to compare data in a std::array
container to a std::vector
container, again, I will have to create another function. I would like to create a single templated member function that I can pass any type of container to the function and have it compare it against any other type of container. In other words instead of;
void UnitTest::vectors_are_close(const std::vector<type1> &i, const std::vector<type2> & j);
I would like a simpler function such as;
void UnitTest::arrays_are_close(const type1, const type2);
where type1
and type2
do not just refer to the data in the container, but also the type of container as well. In this way I could pass a std::vector
to type1
and std::array
to type
, or other combinations of the traditional way of creating arrays, array containers and vector containers. Is there any way to facilitate this behavior?
Aucun commentaire:
Enregistrer un commentaire