我正在尝试找到一种使用访问者对std::array
的{{1}}进行汇总的方法。我已经走了这么远,但是我无法一生都想出如何在没有将std::variant
条目添加到访问者lambda列表的开头的情况下推断出访问者类型的问题。
有人知道我可以推断访客中lambda的返回类型的方式,这样我就不必依靠它了?
这就是我现在所拥有的:
void
编辑:我希望结果为#include <array>
#include <iostream>
#include <string_view>
#include <type_traits>
#include <variant>
using namespace std::literals::string_view_literals;
template<typename... Base>
struct Visitor: Base ... {
using Base::operator()...;
};
template<typename... T>
Visitor(T...) -> Visitor<T...>;
// There has to be a better way to deduce Result than what I'm doing...
template<typename... T, typename S, typename... Ss, size_t N, typename Result = typename std::result_of_t<S()>>
constexpr std::enable_if_t<std::is_arithmetic_v<Result>, Result>
summation(const Visitor<S, Ss...> &visitor, const std::array<std::variant<T...>, N> &array) {
Result sum{};
for (const auto &a: array)
sum += std::visit(visitor, a);
return sum;
}
int main() {
constexpr Visitor visitor {
// This first entry should be unnecessary, I would think:
[]() -> double { return 0; },
[](double d) -> double { return d + 3.4; },
[](int i) -> double { return i - 2; },
[](std::string_view s) -> double { return s.size(); }
};
constexpr std::array<std::variant<int, double, std::string_view>, 5> arr{9.0, 9, 3, 5.2, "hello world"sv};
constexpr auto val = summation(visitor, arr);
std::cout << val << '\n';
}
。
感谢您的帮助。
答案 0 :(得分:2)
当var startTime = '03:00 AM';
var newStartTime = startTime;
var endTime = '05:00 AM';
var minutes=0;
var hours=0;
var timeArray=[];
var ampm='';
var executing=true;
while(executing) {
timeArray.push(newStartTime);
minutes = Number(minutes) + 30;
hours = newStartTime.split(' ')[0].split(':')[0]
ampm= newStartTime.split(' ')[1];
if(minutes > 59) {
if(Number(hours) > 12) {
ampm = newStartTime.split(' ')[1] == 'AM'?'PM':'AM';
hours = '01';
}
else {
hours = Number(hours) + 1;
if(hours.toString().length ==1) {
hours = '0' + hours;
}
}
minutes = minutes - 60;
}
if(minutes.toString().length ==1) {
minutes = '0' + minutes;
}
newStartTime = hours + ':' + minutes+' ' +ampm;
if(Number(newStartTime.split(' ')[0].split(':')[0]) > Number(endTime.split(' ')[0].split(':')[0])){
if(newStartTime.split(' ')[1] == endTime.split(' ')[1])
executing = false;
}
else if(Number(newStartTime.split(' ')[0].split(':')[0]) == Number(endTime.split(' ')[0].split(':')[0])) {
if(Number(newStartTime.split(' ')[0].split(':')[1]) >= Number(endTime.split(' ')[0].split(':')[1])) {
if(newStartTime.split(' ')[1] == endTime.split(' ')[1])
executing = false;
}
}
}
timeArray.push(endTime);
出现时,您对类型的推断太明确了,以至于编译器会为您代劳。
一旦您处于函数auto
和decltype()
的范围内,就可以轻松进行推断(需要创建默认初始化的目标),因为您可以简单地模拟访问者的实际调用
std::declval()
我实际上更喜欢这种样式,因为错误的调用实际上会产生合理的错误消息,而不是“找不到功能”。那是除非您要尝试针对template<typename... T, typename S, typename... Ss, size_t N>
constexpr auto summation(const Visitor<S, Ss...> &visitor, const std::array<std::variant<T...>, N> &array) {
using Result = decltype(std::visit(visitor, std::declval<std::variant<T...>>()));
static_assert(std::is_arithmetic_v<Result>);
Result sum{};
for (const auto &a: array)
sum += std::visit(visitor, a);
return sum;
}
的非算术版本(这很奇怪)。
答案 1 :(得分:1)
弗兰克的decltype()
/ std::declval()
解决方案的简化(希望如此)。
使用decltype()
/ std::declval()
,您不需要知道S
,Ss...
和T...
;您只需要V
的模板类型visitor
和array
的模板类型。
如果愿意,您也可以避免使用static_assert()
,只需编写即可重新启用SFINAE
template <typename V, typename A,
typename R = decltype(std::visit(std::declval<V>(), std::declval<A>().at(0)))>
constexpr std::enable_if_t<std::is_arithmetic_v<R>, R>
summation(V const & visitor, A const &array)
{
R sum{};
for (const auto &a: array)
sum += std::visit(visitor, a);
return sum;
}