C++实现的各种类型任意嵌套可迭代的求和函数
A Summation Function For Various Type Arbitrary Nested Iterable Implementation in C++
如标题所述,我正在尝试实现一个求和函数,它可以在 C++ 中处理各种类型的任意嵌套可迭代对象。这里的各种类型包括可以加在一起的类型,这里的任意嵌套可迭代的东西包括任何有begin()
和end()
的东西,比如std::vector
和std::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
函数存在一些缺陷
可迭代情况的实现中 return 值的类型始终是 long double
。看来这个 return 类型应该与输入的可迭代值类型相同。
当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
参数,因此该部分失败。
如标题所述,我正在尝试实现一个求和函数,它可以在 C++ 中处理各种类型的任意嵌套可迭代对象。这里的各种类型包括可以加在一起的类型,这里的任意嵌套可迭代的东西包括任何有begin()
和end()
的东西,比如std::vector
和std::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
函数存在一些缺陷
可迭代情况的实现中 return 值的类型始终是
long double
。看来这个 return 类型应该与输入的可迭代值类型相同。当
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
参数,因此该部分失败。