C++实现的各种类型任意嵌套可迭代的求和函数

A Summation Function For Various Type Arbitrary Nested Iterable Implementation in C++

如标题所述,我正在尝试实现一个求和函数,它可以在 C++ 中处理各种类型的任意嵌套可迭代对象。这里的各种类型包括可以加在一起的类型,这里的任意嵌套可迭代的东西包括任何有begin()end()的东西,比如std::vectorstd::array .

template<typename T>
concept Summable = requires(T x) { x + x; };

template<typename T>
concept Iterable = requires(T x)
{
    x.begin();      // must have `x.begin()` 
    x.end();        // and `x.end()` 
};

template<typename T> requires Summable<T>
static T Sum(T inputNumber);        //  Deal with the base case like "Sum(static_cast<int>(1))"

template<class T> requires Iterable<T>
static auto Sum(const T& numbers);  //  Deal with the iterable case like "Sum(std::vector<long double>{ 1, 1, 1 })"


template<class T> requires Summable<T>
static inline T Sum(T inputNumber)
{
    return inputNumber;
}

template<class T>  requires Iterable<T>
static inline auto Sum(const T& numbers)
{
    long double sumResult = 0.0;
    for (auto& element : numbers)
    {
        sumResult = sumResult + Sum(element);
    }
    return sumResult;
}

测试用例如下。

long double testNumber = 1;
    
std::vector<decltype(testNumber)> testVector1;
testVector1.push_back(testNumber);
testVector1.push_back(testNumber);
testVector1.push_back(testNumber);
std::cout << Sum(testVector1) << std::endl;

std::vector<decltype(testVector1)> testVector2;
testVector2.push_back(testVector1);
testVector2.push_back(testVector1);
testVector2.push_back(testVector1);
std::cout << Sum(testVector2) << std::endl;

std::vector<decltype(testVector2)> testVector3;
testVector3.push_back(testVector2);
testVector3.push_back(testVector2);
testVector3.push_back(testVector2);
std::cout << Sum(testVector3) << std::endl;

//  std::array test case
std::array<long double, 90> numberArray;
for (size_t i = 0; i < 90; i++)
{
    numberArray[i] = 1;
}
std::cout << std::to_string(Sum(numberArray)) + "\n";

但是上面的Sum函数存在一些缺陷

  1. 可迭代情况的实现中 return 值的类型始终是 long double。看来这个 return 类型应该与输入的可迭代值类型相同。

  2. std::complex类型不是built-in数值类型时,这个sum函数就不行了。

我尝试将Sum函数修改为以下版本

template<class T>  requires Iterable<T>
static inline auto Sum(const T& numbers)
{
    typename std::iterator_traits<T::iterator>::value_type sumResult = 0.0;     //  Update "long double" into "typename std::iterator_traits<T::iterator>::value_type"
    for (auto& element : numbers)
    {
        sumResult = sumResult + Sum(element);
    }
    return sumResult;
}

那么,在std::vector<>的情况下效果很好。但是,typename std::iterator_traits<T::iterator>::value_type 无法处理 multi-nested 可迭代的情况,例如 std::vector<std::vector<std::complex>>std::vector<std::vector<std::vector<std::complex>>>。这个问题有什么可能的解决方案吗?

欢迎所有建议。

你只需要更聪明地推导sumResult的类型:

template<class T>  requires Iterable<T>
static inline auto Sum(const T& numbers)
{
    typedef typename std::iterator_traits<typename T::iterator>::value_type
        value_type;

    decltype(Sum(std::declval<value_type &&>())) sumResult{};

    for (auto& element : numbers)
    {
        sumResult = sumResult + Sum(element);
    }
    return sumResult;
}

通过此更改,显示的代码编译为

std::complex<double> testNumber{1,0};

并编译涉及a

的计算
std::array<std::complex<double>, 90> numberArray;

但是 std::to_string 没有合适的重载以 std::complex 参数,因此该部分失败。