【问题标题】:Creating a C++ template function that allows multiple types of array containers创建允许多种类型的数组容器的 C++ 模板函数
【发布时间】:2019-04-23 13:56:54
【问题描述】:

在现代 C++ 中,您可以通过以下三种主要方法创建数组。

// 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}

虽然每个数组方法都包含相同的数据,但它们本质上是不同的容器。我正在编写一个非常简单的带有模板函数的单元测试类,以便更轻松地传递多种数据类型。对于.hpp.cpp 调用文件,我有一个如下所示的示例。文件中显示的一种方法采用 std::vector 并将其与另一个 std::vector 指数逐个指数进行比较,以确保每个值都在另一个值的特定容差范围内。

// 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;
}

#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";
    }
}

在这个例子中,代码比较了两个向量;但是,如果我想比较 std::array 容器,我将不得不创建一个全新的函数来做到这一点,如果我想比较两个通用数组,我将不得不再次创建另一个函数来做到这一点。此外,如果我想将std::array 容器中的数据与std::vector 容器中的数据进行比较,我将不得不再次创建另一个函数。我想创建一个模板化的成员函数,我可以将任何类型的容器传递给该函数,并让它与任何其他类型的容器进行比较。换句话说,而不是;

void UnitTest::vectors_are_close(const std::vector<type1> &i, const std::vector<type2> & j);

我想要一个更简单的函数,例如;

void UnitTest::arrays_are_close(const type1, const type2);

其中type1type2 不仅仅指容器中的数据,还指容器的类型。通过这种方式,我可以将std::vector 传递给type1,将std::array 传递给type,或者其他传统方式的创建数组、数组容器和向量容器的组合。有什么方法可以促进这种行为?

【问题讨论】:

    标签: c++11 templates c++17


    【解决方案1】:

    通过对您的实现进行一些更改,可以做到这一点:

    template <class container1, class container2>
    void UnitTest::vectors_are_close(const container1 &i, const container2 &j,
                                     double k, std::string str)
    {
        unsigned long remain;
        remain = 50 - str.length();
        if (std::size(i) != std::size(j)) {
            std::cout << str + std::string(remain, '.') +
            std::string("FAILED") << std::endl;
        }
        else {
            try {
                for (int a = 0; a < std::size(i); 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;
             }
        }
    }
    

    这个函数应该适用于 std::vector、std::array 和 C 风格的数组。

    【讨论】:

    • 谢谢,我误以为您只能将数据类型传递给模板,而不能传递给结构或容器。这很强大!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 1970-01-01
    相关资源
    最近更新 更多