在运行时询问变体中的替代是否满足某个概念
Asking at runtime if alternative in variant satisfies a certain concept
我有以下代码,我尝试在其中检测变体中的替代概念(在本例中为成员函数)。它很冗长,相对丑陋。有没有更好的方法可以做到这一点?请注意,我不想使用继承,也不想使用静态多态性(假设在编译时不知道使用什么引擎)。
简单来说,我正在寻找if constexpr
(仅在编译时检查概念)和std::holds_alternative
(只能检查特定类型是否在variant
中,而不是满足该概念的任何类型是否在variant
中)的运行时组合。
#include <iostream>
#include <variant>
struct simple_engine1{
};
struct simple_engine2{
};
struct complex_engine1{
void reduce_thrust(int perc){
std::cout<<"reducing thrust " << perc << "% " << std::endl;
}
};
struct complex_engine2{
void reduce_thrust(int perc){
std::cout<<"reducing thrust " << perc << "% " << std::endl;
}
};
template< class, class = std::void_t<> >
struct has_reduce_thrust : std::false_type { };
template< class T >
struct has_reduce_thrust<T,
std::void_t<decltype( std::declval<T>().reduce_thrust(42) )>
> : std::true_type { };
static_assert(!has_reduce_thrust<simple_engine1>::value);
static_assert(!has_reduce_thrust<simple_engine1>::value);
static_assert(has_reduce_thrust<complex_engine1>::value);
struct visitor{
template<typename T>
void operator()(T& t){
dispatch(t, has_reduce_thrust<T>{});
}
template<typename T>
void dispatch(T& t, std::true_type /*has_reduce_thrust*/){
t.reduce_thrust(perc);
reduced_thrust=true;
}
template<typename T>
void dispatch(T& , std::false_type){
reduced_thrust=false;
}
int perc = 0;
bool reduced_thrust = false;
};
// tries to reduce speed by reducing thrust if engine supports it, if not
// it fires reverse engines(more expensive wrt fuel usage)
void reduce_speed(std::variant<simple_engine1, simple_engine2, complex_engine1, complex_engine2>* var_engine){
visitor v;
v.perc = 47;
std::visit(v, *var_engine);
if (v.reduced_thrust) {
std::cout << "reduced thrustn";
} else {
std::cout << "activating reverse enginesn";
}
}
int main() {
std::variant<simple_engine1, simple_engine2, complex_engine1, complex_engine2> var_engine{simple_engine1{}};
reduce_speed(&var_engine);
var_engine = complex_engine2{};
reduce_speed(&var_engine);
var_engine = simple_engine2{};
reduce_speed(&var_engine);
var_engine = complex_engine2{};
reduce_speed(&var_engine);
}
您可以使用if constexpr
大大简化访问者:
struct visitor{
template<typename T>
void operator()(T& t) {
if constexpr (has_reduce_thrust<T>::value) {
t.reduce_thrust(perc);
reduced_thrust = true;
}
else {
reduced_thrust = false;
}
}
int perc = 0;
bool reduced_thrust = false;
};
然后,您可以通过接受if constexpr
任一分支的任何谓词和两个函数来进一步抽象:
template <template <class, class... /*SFINAE friendly*/> class TypePred,
class MatchedFunc, class UnmatchedFunc>
class predicated_visitor {
public:
predicated_visitor(MatchedFunc matchedFunc, UnmatchedFunc unmatchedFunc)
: _matchedFunc(matchedFunc), _unmatchedFunc(unmatchedFunc) {}
template <typename T>
void operator()(T& t) {
if constexpr (TypePred<T>::value)
_matchedFunc(t);
else
_unmatchedFunc(t);
}
private:
MatchedFunc _matchedFunc;
UnmatchedFunc _unmatchedFunc;
};
template <template <class, class... /*SFINAE friendly*/> class TypePred,
class F1, class F2>
auto makePredicatedVisitor(F1 f1, F2 f2) {
return predicated_visitor<TypePred, F1, F2>(f1, f2);
}
我觉得生成的代码非常好:
void reduce_speed(std::variant<simple_engine1, simple_engine2, complex_engine1,
complex_engine2>* var_engine) {
int perc = 47;
bool reducedThrust = false;
auto reduceableThrustAction = [perc, &reducedThrust](auto& t) {
t.reduce_thrust(perc);
reducedThrust = true;
};
auto alternativeAction = [](auto& t) {
}; // Could explicitly set reduceThrust to false for clarity.
auto thrust_visitor = makePredicatedVisitor<has_reduce_thrust>(
reduceableThrustAction, alternativeAction);
std::visit(thrust_visitor, *var_engine);
if (reducedThrust) {
std::cout << "reduced thrustn";
} else {
std::cout << "activating reverse enginesn";
}
}
演示
此示例编译为与您的程序集代码基本相同的程序集代码,但可以以您喜欢的任何方式重用。
对于大小写不一致,我深表歉意...
相关文章:
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- "<"满足严格的弱排序是否意味着不需要"=="定义?
- 在不再满足条件后,while 循环是否停止验证?
- 什么 STL 算法可以确定容器中的一个项目是否满足谓词?
- C++概念是否允许我的类在声明/定义中指定它满足某些概念?
- 检查是否所有 std::元组元素都满足条件 + 设计问题
- 检查变量是否满足没有呼叫的过载功能
- 在运行时询问变体中的替代是否满足某个概念
- 当满足条件时,是否可以在 GLSL 着色器中回调 C/C++ 函数/代码
- if 语句贯穿始终,无论是否满足条件
- g++是否满足std::string C++11的要求
- CRTP-从基类中检查派生类是否满足要求
- 检查是否满足任意不等式的列表
- C++该类型是否应满足std::is_copy_assignable
- 浮点数的无限是否满足这些方程
- 如何确保我的代码是ansi C,不涉及C++.像gcc这样的编译器是否可以设置为在满足C++中的功能时提示错误
- 检查循环中出现的任何条件是否已满足c++
- 循环中字符串的输出会根据是否满足某个条件而变化
- 在C++如何验证是否满足某些条件