如何在 Google Test 中使用不同模板测试多个模板类的相同行为?

2024-01-12

我正在练习 C++ 17 中的排序算法,并按如下方式实现了我的单元测试(以下编译和所有测试都是绿色的):

template <typename T>
class SortingmethodTest : public ::testing::Test
{
protected:   
    T sortingmethod;

    static constexpr int amount_test_data[7] = {0, 4, 8, 10, 256, 1000, 1234};
};

using sortingmethods = ::testing::Types<STLSort<int>,
                                         InsertionSort<int>,
                                         ShellSort<int>,
                                         MergeSort<int>,
                                         OptimizedMergeSort<int>,
                                         QuickSort<int>>;

TYPED_TEST_SUITE(SortingmethodTest, sortingmethods);

TYPED_TEST(SortingmethodTest, sort)
{
    for (const auto& amount : this->amount_test_data)
    {
        Sortvector<int> test(amount);
        test.vul_random_zonder_dubbels(); // Fills the vector

        this->sortingmethod(test); // operator() of the sortmethod used (STLSort, InsertionSort, ...) sorts the vector

        ASSERT_TRUE(test.is_range());
        ASSERT_TRUE(test.is_gesorteerd());
        ASSERT_TRUE(std::is_sorted(test.begin(), test.end()));
    }
}

TYPED_TEST(SortingmethodTest, sort_reverse)
{
    // ...
}

TYPED_TEST(SortingmethodTest, sort_already_sorted)
{
    // ...
}

TYPED_TEST(SortingmethodTest, sort_empty)
{
    // ...
}

我想对除整数之外的其他类型重复相同的测试,例如

STLSort<int>,
InsertionSort<int>,
ShellSort<int>,
MergeSort<int>,
OptimizedMergeSort<int>,
QuickSort<int>

STLSort<double>,
InsertionSort<double>,
ShellSort<double>,
MergeSort<double>,
OptimizedMergeSort<double>,
QuickSort<double>

STLSort<CustomType>,
InsertionSort<CustomType>,
ShellSort<CustomType>,
MergeSort<CustomType>,
OptimizedMergeSort<CustomType>,
QuickSort<CustomType>

...

我怎样才能在 C++ 中使用 google test 尽可能干净地并尽可能多地重用呢?我在类型测试和类型参数化测试的丛林中迷失了方向 [1]:我什么时候应该使用其中之一?

亲切的问候,

Marten

[1] https://github.com/google/googletest/blob/master/docs/advanced.md#type-parameterized-tests https://github.com/google/googletest/blob/master/docs/advanced.md#type-parameterized-tests


令人沮丧的是,到目前为止 googletest API 并没有为我们提供更多的信息 利用现代C++使测试代码简洁,特别是对于 模板。但直到 v1.8.x(当前版本系列位于 截至目前)googletest 已致力于 C++98 兼容性,这就是主要原因。 即将发布的 1.9.x 将继续兼容 C++11,我们希望 以获得更强大的 API。

尽管如此,现在可以编写相当简洁和直接的 googletest 代码来 做你想要的事情:也就是说,对一致模板进行单元测试,以获取仅一个的不同值 模板参数。

有不止一种方法可以做到这一点。这是其中之一的一个有效示例, 使用类型参数化测试 https://github.com/google/googletest/blob/master/docs/advanced.md#type-parameterized-tests.

我们将有一组三个模板

template<typename T> struct (AA|BB|CC) {...};

每个都提供(至少)接口:

Name::Name(T const & u);
Name::operator int() const;
Name Name::operator+(Name const & u) const;
Name & Name::operator+=(Name const & u);
Name Name::operator-(Name const & u) const;
Name & Name::operator-=(Name const & u);

for Name = (AA|BB|CC)。我们想 对每个接口进行单元测试(AA|BB|CC),每个实例化为 六种类型中的每一种:

char, int, float, AA<char>, BB<int>, CC<float>

因此需要测试 18 个实例:

AA<char>, AA<int>, AA<float>, AA<AA<char>>, AA<BB<int>>, AA<CC<float>>
BB<char>, BB<int>, BB<float>, BB<AA<char>>, BB<BB<int>>, BB<CC<float>>
CC<char>, CC<int>, CC<float>, CC<AA<char>>, CC<BB<int>>, CC<CC<float>>

为了简单起见,我们将只实现两个通用测试。对于物体a, b and c任何实例化测试类型:

  • After a = b + c; b += c, then a == b.
  • Given b != c, after a = b - c; c -= b, then a != c.

(至少,只要操作不溢出或不溢出,这些属性就应该保持 失去精度,我会避免这种情况)。

所以我们预计会看到 36 项测试。

对于这个插图我不在乎什么AA, BB and CC除了它们的通用接口之外, 所以我只是从一个模型中以相同的方式导出它们,如下所示:

一些_类型.h

#pragma once

#include <type_traits>

namespace detail {
    template<typename T>
    struct bottom_type {
        using type = T;
    };

    template<template<typename ...> class C, typename ...Ts>
    struct bottom_type<C<Ts...>> {
        using type = typename C<Ts...>::type;
    };
}

template<typename T>
using bottom_t = typename detail::bottom_type<T>::type;

template<
    typename T,
    typename Enable = std::enable_if_t<std::is_arithmetic_v<bottom_t<T>>>
>
struct model
{
    using type = bottom_t<T>;

    model() = default;
    model(model const &) = default;
    model(T const & t)
    : _t{t}{}

    operator type() const { return _t; }

    auto operator+(model const & u) const {
        return _t + u;
    }

    auto & operator+=(model const & u) {
        _t += u;
        return *this;
    }

    auto operator-(model const & u ) const {
        return _t - u;
    }

    auto & operator-=(model const & u ) {
        _t -= u;
        return *this;
    }

protected:
    type _t = 0;
};

template<typename T> struct AA : model<T>{ using model<T>::model; };
template<typename T> struct BB : model<T>{ using model<T>::model; };
template<typename T> struct CC : model<T>{ using model<T>::model; };

现在这是我的谷歌测试代码:

main.cpp

#include <array>
#include <algorithm>
#include <random>
#include <type_traits>
#include <limits>
#include <gtest/gtest.h>
#include "some_types.h"

template<typename T>
struct fixture : public ::testing::Test
{
protected:

    template<typename U>
    static auto const & test_data() {
        using type = bottom_t<U>;
        static std::array<type,1000> data;
        static bool called;
        if (!called) {
            std::default_random_engine gen;
            auto low = std::numeric_limits<type>::min() / 2;
            auto high = std::numeric_limits<type>::max() / 2;
            auto dist = [&low,&high](){
                if constexpr (std::is_floating_point_v<type>) {
                    return std::uniform_real_distribution<type>(low,high);
                } else {
                    return std::uniform_int_distribution<type>(low,high);
                }
            }();
            std::generate(
                data.begin(),data.end(),[&dist,&gen](){ return dist(gen); });
            called = true;
        }
        return data;
    }
};


template<template<typename> class C, typename ...Ts>
using test_types = ::testing::Types<C<Ts>...>;

using AA_test_types = test_types<AA,char,int,float,AA<char>,BB<int>,CC<float>>;
using BB_test_types = test_types<BB,char,int,float,AA<char>,BB<int>,CC<float>>;
using CC_test_types = test_types<CC,char,int,float,AA<char>,BB<int>,CC<float>>;

TYPED_TEST_SUITE_P(fixture);

TYPED_TEST_P(fixture, addition)
{
    using wrapped_type = typename TypeParam::type;
    auto const & data = this->template test_data<wrapped_type>();
    auto fi = data.begin(); auto ri = data.rbegin();
    for ( ; fi != ri.base(); ++fi, ++ri)
    {
        TypeParam lhs{*fi}, rhs{*ri};
        auto sum = lhs + rhs;
        lhs += rhs;
        ASSERT_EQ(lhs,sum);
    }
}

TYPED_TEST_P(fixture, subtraction)
{
    using wrapped_type = typename TypeParam::type;
    auto const & data = this->template test_data<wrapped_type>();
    auto fi = data.begin(); auto ri = data.rbegin();
    for ( ; fi != ri.base(); ++fi, ++ri) {
        TypeParam lhs{*fi}, rhs{*ri};
        if (lhs != rhs) {
            auto diff = lhs - rhs;
            rhs -= lhs;
            ASSERT_NE(rhs,diff);
        }
    }
}

REGISTER_TYPED_TEST_SUITE_P(fixture,addition,subtraction);
INSTANTIATE_TYPED_TEST_SUITE_P(AA_tests, fixture, AA_test_types);
INSTANTIATE_TYPED_TEST_SUITE_P(BB_tests, fixture, BB_test_types);
INSTANTIATE_TYPED_TEST_SUITE_P(CC_tests, fixture, CC_test_types);

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

让我们看看感兴趣的点:-

template<template<typename> class C, typename ...Ts>
using test_types = ::testing::Types<C<Ts>...>;

在这里,我正在制作test_types的模板别名::testing::Types<SomeType...>列表 在哪里SomeType将是正在测试的模板之一的实例。正如它 发生了,我的模板AA, BB, CC(像你的一样)都是以下形式:

template<typename T> class;

所以我想要test_types成为一个:

::testing::Types<C<Ts>...>

然后我定义了 3 个具体类型别名:

using AA_test_types = test_types<AA,char,int,float,AA<char>,BB<int>,CC<float>>;
using BB_test_types = test_types<BB,char,int,float,AA<char>,BB<int>,CC<float>>;
using CC_test_types = test_types<CC,char,int,float,AA<char>,BB<int>,CC<float>>;

分别相当于:

::testing::Types<AA<char>, AA<int>, AA<float>, AA<AA<char>>, AA<BB<int>>, AA<CC<float>>>;
::testing::Types<BB<char>, BB<int>, BB<float>, BB<AA<char>>, BB<BB<int>>, BB<CC<float>>>;
::testing::Types<CC<char>, CC<int>, CC<float>, CC<AA<char>>, CC<BB<int>>, CC<CC<float>>>;

然后我使用模板夹具定义类型参数化测试套件fixture.

TYPED_TEST_SUITE_P(fixture);

然后我定义两个类型参数化测试模式。

TYPED_TEST_P(fixture, addition)
{
    using wrapped_type = typename TypeParam::type;
    auto const & data = this->template test_data<wrapped_type>();
    auto fi = data.begin(); auto ri = data.rbegin();
    for ( ; fi != ri.base(); ++fi, ++ri)
    {
        TypeParam lhs{*fi}, rhs{*ri};
        auto sum = lhs + rhs;
        lhs += rhs;
        ASSERT_EQ(lhs,sum);
    }
}

TYPED_TEST_P(fixture, subtraction)
{
    using wrapped_type = typename TypeParam::type;
    auto const & data = this->template test_data<wrapped_type>();
    auto fi = data.begin(); auto ri = data.rbegin();
    for ( ; fi != ri.base(); ++fi, ++ri) {
        TypeParam lhs{*fi}, rhs{*ri};
        if (lhs != rhs) {
            auto diff = lhs - rhs;
            rhs -= lhs;
            ASSERT_NE(rhs,diff);
        }
    }
}

然后我在每次实例化时注册这两个模式以进行实例化 的fixture:

REGISTER_TYPED_TEST_SUITE_P(fixture,addition,subtraction);

然后我创建了 3 个实例,名为(AA|BB|CC)_tests of fixture为了 测试类型列表(AA|BB|CC)_test_types分别:

INSTANTIATE_TYPED_TEST_SUITE_P(AA_tests, fixture, AA_test_types);
INSTANTIATE_TYPED_TEST_SUITE_P(BB_tests, fixture, BB_test_types);
INSTANTIATE_TYPED_TEST_SUITE_P(CC_tests, fixture, CC_test_types);

就是这样。编译并链接:

$ g++ -std=c++17 -Wall -Wextra -pedantic -o gtester main.cpp -lgtest -pthread

Run:

./gtester
[==========] Running 36 tests from 18 test suites.
[----------] Global test environment set-up.
[----------] 2 tests from AA_tests/fixture/0, where TypeParam = AA<char>
[ RUN      ] AA_tests/fixture/0.addition
[       OK ] AA_tests/fixture/0.addition (0 ms)
[ RUN      ] AA_tests/fixture/0.subtraction
[       OK ] AA_tests/fixture/0.subtraction (1 ms)
[----------] 2 tests from AA_tests/fixture/0 (1 ms total)

[----------] 2 tests from AA_tests/fixture/1, where TypeParam = AA<int>
[ RUN      ] AA_tests/fixture/1.addition
[       OK ] AA_tests/fixture/1.addition (0 ms)
[ RUN      ] AA_tests/fixture/1.subtraction
[       OK ] AA_tests/fixture/1.subtraction (0 ms)
[----------] 2 tests from AA_tests/fixture/1 (0 ms total)
...
...
...
[----------] 2 tests from CC_tests/fixture/4, where TypeParam = CC<BB<int> >
[ RUN      ] CC_tests/fixture/4.addition
[       OK ] CC_tests/fixture/4.addition (0 ms)
[ RUN      ] CC_tests/fixture/4.subtraction
[       OK ] CC_tests/fixture/4.subtraction (0 ms)
[----------] 2 tests from CC_tests/fixture/4 (0 ms total)

[----------] 2 tests from CC_tests/fixture/5, where TypeParam = CC<CC<float> >
[ RUN      ] CC_tests/fixture/5.addition
[       OK ] CC_tests/fixture/5.addition (0 ms)
[ RUN      ] CC_tests/fixture/5.subtraction
[       OK ] CC_tests/fixture/5.subtraction (0 ms)
[----------] 2 tests from CC_tests/fixture/5 (0 ms total)

[----------] Global test environment tear-down
[==========] 36 tests from 18 test suites ran. (4 ms total)
[  PASSED  ] 36 tests.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Google Test 中使用不同模板测试多个模板类的相同行为? 的相关文章

  • 在 C++ 中使用 matlab 结构(matlab 函数调用的返回值)(由 matlab 编译器生成的库)

    你好 我有一个相当简单的 matlab 函数 例如 function MYSTRUCT myfunc MYSTRUCT prop1 test MYSTRUCT prop2 foo MYSTRUCT prop3 42 end 我用 matla
  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 使用 LINQ2SQL 在 ASP.NET MVC 中的各种模型存储库之间共享数据上下文

    我的应用程序中有 2 个存储库 每个存储库都有自己的数据上下文对象 最终结果是我尝试将从一个存储库检索到的对象附加到从另一个存储库检索到的对象 这会导致异常 Use 构造函数注入将 DataContext 注入每个存储库 public cl
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 使用接口有什么好处?

    使用接口有什么用 我听说它用来代替多重继承 并且还可以用它来完成数据隐藏 还有其他优点吗 哪些地方使用了接口 程序员如何识别需要该接口 有什么区别explicit interface implementation and implicit
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • Qt - ubuntu中的串口名称

    我在 Ubuntu 上查找串行端口名称时遇到问题 如您所知 为了在 Windows 上读取串口 我们可以使用以下代码 serial gt setPortName com3 但是当我在 Ubuntu 上编译这段代码时 我无法使用这段代码 se
  • C# 中的合并运算符?

    我想我记得看到过类似的东西 三元运算符 http msdn microsoft com en us library ty67wk28 28VS 80 29 aspx在 C 中 它只有两部分 如果变量值不为空 则返回变量值 如果为空 则返回默
  • 使用 C# 读取 Soap 消息

  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • System.IO.FileNotFoundException:找不到网络路径。在 Windows 7 上使用 DirectoryEntry 对象时出现异常

    我正在尝试使用 DirectoryEntry 对象连接到远程 Windows 7 计算机 这是我的代码 DirectoryEntry obDirEntry new DirectoryEntry WinNT hostName hostName
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • SQL繁琐添加数组作为参数

    我正在运行这个 SQL 查询tedious js使用参数 var query select from table name where id in ids request new sql Request query function err
  • Laravel Pluck 但结合名字+姓氏进行选择

    在 Laravel Vue 项目中使用 select2 并需要返回以下格式的 JSON id 0 text enhancement id 1 text bug 在 Laravel 中 我知道我可以使用 pluck 来创建列表数据 例如对于客
  • Google 地图信息窗口关闭按钮被隐藏

    我在我的网站中使用了带有多个标记和多个信息窗口的 Google 地图 不知何故 关闭按钮 小x 隐藏在信息窗口内 但如果在应显示的位置单击则可以使用 如何解决这个问题 修复了它 显然 bootstrap css 与图像冲突 必须使用这几行额
  • 如何区分 Google Fit Api 中手动添加的步数和传感器记录的步数

    我在我的项目中使用 Google Fit Api 来获取用户的每日步数 但问题是 用户可以通过添加活动来手动输入步骤 当我检索每日步数时 Google Fit Api 还会返回手动添加的步数 有什么方法可以区分手动添加的步骤和传感器记录的步
  • 适用于 Linux 的 C++ 对象序列化

    我正在编写一个需要通过网络发送和接收数据的程序 我从来没有处理过对象序列化 我读到了一些关于 Boost 和 Google Protocol Buffers 的建议 在 Linux 中使用哪个最好 如果您知道其他人 我将感谢您的帮助 Tha
  • Redis、StackExchange、与 MGET 配合使用,一次获取多个密钥

    有没有办法将 MGET 与 StackExchange Redis C 一起使用 我需要一种方法可以在一次通话中重奏多个按键 可以使用下一个方法 Task
  • 是什么让Python中的东西变得可迭代

    是什么让 Python 中的东西变得可迭代 IE 可以循环它for 我可以用Python创建一个可迭代的类吗 如果是这样 怎么办 要使类可迭代 请编写 iter 返回迭代器的方法 class MyList object def init s
  • CUDA - 如果我选择太多块怎么办?

    我仍然对这些未知大小的矩阵感到生气 每个维度可能在 10 20 000 之间变化 我正在查看 CUDA sdk 并想知道 如果我选择的块数量太高怎么办 就像 X 和 Y 维度上 9999 x 9999 块的网格一样 如果我的硬件具有无法容纳
  • git checkout my_branch 与 git checkout origin/my_branch

    我当时在branch1当我结帐时branch2像这样 两个分支都存在 git checkout origin branch2 然后我得到了一个分离头错误 You are in detached HEAD state You can look
  • 根据给定的 OpenApi/Swagger 规范验证请求负载和响应

    我们有一个 HTTP API 它是用Python 的拥抱框架 http www hug rest 但这并不是一成不变的 将来可能会被其他东西取代 在它旁边 我们手动写了一个OpenApi Swagger 2 0 规范文件 https git
  • 如何设置log4j属性文件?

    我有一个使用 log4j 的 Eclipse Java 项目 我无法将log4j配置文件设置为通过文件路径访问 我必须在 jar 中导出并运行该项目 这是我的尝试 public class Wita static Logger logger
  • ROR-使用回形针逐步生成多个图像

    我已经使用了 教程 here http sleekd com rails adding multiple images to a rails model with paperclip 但由于某种原因它不起作用 任何人都可以给我一个使用其他表
  • 如何每天自动从 git 存储库更新我的服务器文件

    我是这些服务器相关工作的菜鸟 我正在本地系统中编写一些 PHP 代码 并定期更新 github 中的存储库 每次我想测试我的应用程序时 我都会通过 FTP 将本地系统中的所有文件复制到我的服务器上 然后进行测试 现在我想知道是否有一种方法可
  • 服务和组件属性之间的 Angular2 数据绑定

    我需要对服务和组件属性之间的绑定以及 Angular2 中的数据绑定进行一些澄清 假设我有一个服务 单例 和一个组件 export class Service name Luke object id 1 getName return thi
  • 使用python提取一个句子

    如果该句子中存在特定单词 我想提取确切的句子 谁能告诉我如何用 python 做到这一点 我使用了 concordance 但它只打印单词匹配的行 快速提醒一下 断句实际上是一件非常复杂的事情 句号规则也有例外 例如 先生 或 博士 还有各
  • AttributeError:“KMeans”对象没有属性“inertia_”

    from sklearn cluster import KMeans import numpy import pandas as pd from pandas import read csv boston read csv desktop
  • 计算两个点阵列之间的成对角度矩阵

    我有两个点向量 x and y 成形 n p and m p 分别 举个例子 x np array 0 0 16341 0 98656 0 05937 0 25205 0 96589 0 05937 0 25205 0 96589 0 11
  • 在函数 (group_by) 中使用 dplyr 时出现问题

    我想使用 dplyr 进行一些数据操作 背景 我有一个调查权重和一堆变量 主要是李克特项目 我想对有和没有调查权重的每个类别的频率和百分比进行求和 举个例子 让我们只使用性别变量的频率 结果应该是这样的 gender freq freq w
  • 哪个 .NET 库具有写时复制集合?

    我正在搜索要在 C 程序中使用的 NET 写时复制集合 例如列表 字典等 哪些集合具有该属性 包括参考FSharp Core 然后你就可以访问多种不可变的集合 Set List Map etc 这些位于Microsoft FSharp Co
  • 如何在 Google Test 中使用不同模板测试多个模板类的相同行为?

    我正在练习 C 17 中的排序算法 并按如下方式实现了我的单元测试 以下编译和所有测试都是绿色的 template