对不起,如果这个案例相当复杂,但我希望它可以帮助人们更好地理解现代 c++ 的用法。所以我想让这段代码工作。它应该为单个整数类型和变体类型生成特殊的 lambda,用于计算硬静态转换为单一类型或软变体转换为通用类型的术语序列,而这些术语将被使用。我添加了描述我在这段代码中真正尝试做的事情的注释。
#include <variant>
#include <type_traits>
#include <string>
#include <functional>
#include <iostream>
#include <memory>
#include <optional>
#include <any>
#include <utility>
/* Visitor */
// Should get values from a variant
template <class... Ts>
struct Visitor;
template <class T, class... Ts>
struct Visitor<T, Ts...> : T, Visitor<Ts...> {
Visitor(T t, Ts... rest) : T(t), Visitor<Ts...>(rest...) {}
using T::operator();
using Visitor<Ts...>::operator();
};
template <class T>
struct Visitor<T> : T {
Visitor(T t) : T(t) {}
using T::operator();
};
/* Calculator */
// Should get special lambda for same type integrals and for variant packed integrals
template<class T, class... Ts>
class Calculator {
public:
// lambda for simple calculate same type integrals
static auto sum = [](T a, T b) { return a + b; };
// api for get current value of variant
template<typename... Vs>
static auto variant_value(std::variant<Vs...> v) {
return std::visit(Visitor<Vs...>{}, v);
}
// lambda for unpack variant arguments calc common value and pack in variant again
template<typename... Vs>
static auto variant_sum = [](std::variant<Vs...> a, std::variant<Vs...> b) {
auto value = variant_value<Vs...>(a) + variant_value<Vs...>(b);
return std::variant<Vs...>(value);
};
};
/* Term Producer */
namespace term::legion {
using std::function, std::any;
template<typename T>
function<any(any)> legion(auto& algebra) noexcept { // std::function<T(T,T...)
function<any(any)> redex = [](std::any a) {return a;};
// I delete code here because its not important now
return redex;
}
// production lamda for single type values
template<typename T>
std::function<std::any(std::any)> sum(T arg) noexcept {
return legion<T>(Calculator<T>::sum);
};
// production lambda for variant type values
template<typename ...Vs>
std::function<std::any(std::any)> sum() noexcept {
std::cout << "variant sum selected" << std::endl;
return legion<std::variant<Vs...>>(Calculator<Vs...>::template variant_sum<Vs...>);
};
}
int main() {
// term contains lambda for single type
auto sm = term::legion::sum<int>();
// term contains lambda for variant type
auto v_sm = term::legion::sum<char, int16_t, double>();
}