首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >recursive_count函数与recursive_depth在C++中进行unwrap_level检查

recursive_count函数与recursive_depth在C++中进行unwrap_level检查
EN

Code Review用户
提问于 2021-10-29 00:13:02
回答 2查看 49关注 0票数 1

这是递推_在C++中计算嵌套类型实现深度的深度函数递推_C++中各种类型任意嵌套Iterable实现的解包装计数函数的后续问题.我试图遵循格·斯利平的答复实现另一个版本的recursive_count函数,使用recursive_depth进行unwrap_level检查。

The实验实现

  • recursive_count函数: // recursive_count实现// recursive_count实现(unwrap_level版本) template constexpr recursive_count(const T& input,const auto& target) { if constexpr (unwrap_level> 0) { static_assert(unwrap_level <= recursive_depth(),“展开级别高于递归输入深度”);返回std::transform_reduce(std::ranges::cbegin(input),std::范围::cend(输入),std::size_t{},std::plus(),&目标 {返回recursive_count(元素,目标);}}{返回0;}} // recursive_count实现(不含unwrap_level的版本) template constexpr recursive_count(const Range& input,const auto& target) {返回unwrap_level目标);}
  • recursive_depth>()函数: // recursive_depth函数实现template std::size_t recursive_depth() {返回0;} template template

The测试代码

代码语言:javascript
复制
void recursive_count_test()
{
    std::vector test_vector{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 };
    std::cout << recursive_count<1>(test_vector, 5) << '\n';

    //  std::vector>
    std::vector test_vector2{ test_vector , test_vector , test_vector };
    std::cout << recursive_count<2>(test_vector2, 5) << '\n';

    //  std::vector
    std::vector test_string_vector{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" };
    std::cout << recursive_count<1>(test_string_vector, "0") << '\n';

    //  std::vector>
    std::vector test_string_vector2{ test_string_vector , test_string_vector , test_string_vector };
    std::cout << recursive_count<2>(test_string_vector2, "0") << '\n';

    //  std::deque
    std::deque test_deque;
    test_deque.push_back(1);
    test_deque.push_back(2);
    test_deque.push_back(3);
    test_deque.push_back(4);
    test_deque.push_back(5);
    test_deque.push_back(6);
    std::cout << recursive_count<1>(test_deque, 1) << '\n';

    //  std::deque>
    std::deque test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    std::cout << recursive_count<2>(test_deque2, 1) << '\n';

    //  std::list
    std::list test_list = { 1, 2, 3, 4, 5, 6 };
    std::cout << recursive_count<1>(test_list, 1) << '\n';


    //  std::list>
    std::list> test_list2 = { test_list, test_list, test_list, test_list };
    std::cout << recursive_count<2>(test_list2, 1) << '\n';

    std::cout << recursive_count<11>(
        n_dim_container_generator<10, std::list>(test_list, 3),
        1
        ) << '\n';
}

Full测试代码

完整的测试代码:

代码语言:javascript
复制
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

//  recursive_depth function implementation
template
constexpr std::size_t recursive_depth()
{
    return 0;
}

template
constexpr std::size_t recursive_depth()
{
    return recursive_depth>() + 1;
}

//  recursive_count implementation

//  recursive_count implementation (the version with unwrap_level)
template
constexpr auto recursive_count(const T& input, const auto& target)
{
    if constexpr (unwrap_level > 0)
    {
        static_assert(unwrap_level <= recursive_depth(),
            "unwrap level higher than recursion depth of input");
        return std::transform_reduce(std::ranges::cbegin(input), std::ranges::cend(input), std::size_t{}, std::plus(), [&target](auto&& element) {
            return recursive_count(element, target);
            });
    }
    else
    {
        if (input == target)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

//  recursive_count implementation (the version without unwrap_level)
template
constexpr auto recursive_count(const Range& input, const auto& target)
{
    return recursive_count()>(input, target);
}

template
constexpr auto n_dim_vector_generator(T input, std::size_t times)
{
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        auto element = n_dim_vector_generator(input, times);
        std::vector output(times, element);
        return output;
    }
}

template
constexpr auto n_dim_array_generator(T input)
{
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        auto element = n_dim_array_generator(input);
        std::array output;
        std::fill(std::begin(output), std::end(output), element);
        return output;
    }
}

template
constexpr auto n_dim_deque_generator(T input, std::size_t times)
{
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        auto element = n_dim_deque_generator(input, times);
        std::deque output(times, element);
        return output;
    }
}

template
constexpr auto n_dim_list_generator(T input, std::size_t times)
{
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        auto element = n_dim_list_generator(input, times);
        std::list output(times, element);
        return output;
    }
}

template class Container = std::vector, class T>
constexpr auto n_dim_container_generator(T input, std::size_t times)
{
    if constexpr (dim == 0)
    {
        return input;
    }
    else
    {
        return Container(times, n_dim_container_generator(input, times));
    }
}

void recursive_depth_test();
void recursive_count_test();

int main()
{
    recursive_count_test();
}

void recursive_depth_test()
{
    //  non-nested type `char`
    char test_char = 'A';
    std::cout << recursive_depth() << '\n';
    
    //  non-nested type `int`
    int test_int = 100;
    std::cout << recursive_depth() << '\n';
    
    //  std::vector
    std::vector test_vector{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 };
    std::cout << recursive_depth() << '\n';

    //  std::vector>
    std::vector test_vector2{ test_vector , test_vector , test_vector };
    std::cout << recursive_depth() << '\n';

    //  std::deque
    std::deque test_deque;
    test_deque.push_back(1);
    test_deque.push_back(2);
    test_deque.push_back(3);
    test_deque.push_back(4);
    test_deque.push_back(5);
    test_deque.push_back(6);
    std::cout << recursive_depth() << '\n';

    //  std::deque>
    std::deque test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    std::cout << recursive_depth() << '\n';

    //  std::list
    std::list test_list = { 1, 2, 3, 4, 5, 6 };
    std::cout << recursive_depth() << '\n';


    //  std::list>
    std::list> test_list2 = { test_list, test_list, test_list, test_list };
    std::cout << recursive_depth() << '\n';
}

void recursive_count_test()
{
    std::vector test_vector{ 5, 7, 4, 2, 8, 6, 1, 9, 0, 3 };
    std::cout << recursive_count<1>(test_vector, 5) << '\n';

    //  std::vector>
    std::vector test_vector2{ test_vector , test_vector , test_vector };
    std::cout << recursive_count<2>(test_vector2, 5) << '\n';

    //  std::vector
    std::vector test_string_vector{ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20" };
    std::cout << recursive_count<1>(test_string_vector, "0") << '\n';

    //  std::vector>
    std::vector test_string_vector2{ test_string_vector , test_string_vector , test_string_vector };
    std::cout << recursive_count<2>(test_string_vector2, "0") << '\n';

    //  std::deque
    std::deque test_deque;
    test_deque.push_back(1);
    test_deque.push_back(2);
    test_deque.push_back(3);
    test_deque.push_back(4);
    test_deque.push_back(5);
    test_deque.push_back(6);
    std::cout << recursive_count<1>(test_deque, 1) << '\n';

    //  std::deque>
    std::deque test_deque2;
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    test_deque2.push_back(test_deque);
    std::cout << recursive_count<2>(test_deque2, 1) << '\n';

    //  std::list
    std::list test_list = { 1, 2, 3, 4, 5, 6 };
    std::cout << recursive_count<1>(test_list, 1) << '\n';


    //  std::list>
    std::list> test_list2 = { test_list, test_list, test_list, test_list };
    std::cout << recursive_count<2>(test_list2, 1) << '\n';

    std::cout << recursive_count<11>(
        n_dim_container_generator<10, std::list>(test_list, 3),
        1
        ) << '\n';
}

上帝的链接在这里。

欢迎所有建议。

摘要资料:

EN

回答 2

Code Review用户

回答已采纳

发布于 2021-10-29 07:27:52

缺失测试用例

我没有看到为不需要展开级别的recursive_count()版本添加任何测试用例。另外,为角用例添加测试用例,最重要的是尝试在范围上应用recursive_count<0>(),在非范围上应用recursive_count()。例如,考虑添加以下测试用例:

代码语言:javascript
复制
assert(recursive_count<0>(1, 2) == 0);
assert(recursive_count<0>(0, 0) == 1);

这将正确地编译和运行。然而,以下并不是:

代码语言:javascript
复制
assert(recursive_count(1, 2) == 0);
assert(recursive_count(0, 0) == 1);

这将无法与代码一起编译,因为没有展开级别的recursive_count()只在范围内工作。修复方法是使其成为template而不是template

票数 2
EN

Code Review用户

发布于 2021-10-29 14:42:47

代码语言:javascript
复制
       if (input == target)
        {
            return 1;
        }
        else
        {
            return 0;
        }

把这个写得很清楚:return (input == target) ? 1 : 0;

您编写的代码的认知开销相当高:读者看到一个if语句,所以代码做了两件不同的事情。然后,每件事都是一个返回语句。啊,它以任何方式返回,你总是想要返回--你只想条件指定返回哪个值。

所以直接写出来,而不是让读者反其道而行。

我想给大家留下深刻的印象,这不仅仅是为了“简洁”而已。单一语句更容易阅读和理解,因为它直接声明了意图。通常,在条件分支中不要重复不必要的内容。如果条件只是影响某些值,则不要重复函数调用和未受影响的值。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/269479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档