英文:
Get list of types for which templated member method is specialized
问题
以下是您要翻译的代码部分:
我为我的FSM实现编写了以下基础代码:
template <typename... Ts>
struct BaseState {
template <typename T>
static bool canTransition() {
if constexpr((std::is_same_v<T, Ts> || ...)) return true;
return false;
}
};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool canTransition = std::visit([](auto&& arg) { return arg.template canTransition<T>(); }, active);
if (!canTransition) return false;
std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
active.template emplace<T>();
return true;
}
};
struct B;
struct A : BaseState<B> {
template <typename T>
void onExit() {}
template <>
void onExit<B>() { std::cout << "A -> B" << std::endl; }
};
struct B : BaseState<> {
template <typename T>
void onExit() {};
};
int main() {
StateMachine<A, B> sm;
sm.activate<B>(); // A -> B
sm.activate<A>(); // 不应该切换状态
}
'onExit'成员方法允许我基于新状态类型执行一些操作。
我希望根据'onExit'的特化自动推断A和B的模板参数,这样我就不需要手动指定所有状态可以过渡到的特定状态。
我还考虑将'template <typename T> void onExit() {}'的定义移动到'BaseState'类中,但是似乎不能专门化继承的模板成员方法。
作为替代方案,我考虑从'onExit'方法中返回布尔值,指示是否应转换状态,如下所示:
struct BaseState {};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool canTransition = std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
if (!canTransition) return false;
active.template emplace<T>();
return true;
}
};
struct B;
struct A : BaseState {
template <typename T>
bool onExit() { return false; }
template <>
bool onExit<B>() { std::cout << "A -> B" << std::endl; return true; }
};
struct B : BaseState {
template <typename T>
bool onExit() { return false; }
};
int main() {
StateMachine<A, B> sm;
sm.activate<B>(); // A -> B
sm.activate<A>(); // 不应切换状态
}
然而,我不太喜欢手动指定返回值的想法。
我有哪些选择?
英文:
I wrote a following base code for my FSM implementation:
template <typename... Ts>
struct BaseState {
template <typename T>
static bool canTransition() {
if constexpr((std::is_same_v<T, Ts> || ...)) return true;
return false;
}
};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool canTransition = std::visit([](auto&& arg) { return arg.template canTransition<T>(); }, active);
if (!canTransition) return false;
std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
active.template emplace<T>();
return true;
}
};
struct B;
struct A : BaseState<B> {
template <typename T>
void onExit() {}
template <>
void onExit<B>() { std::cout << "A -> B" << std::endl; }
};
struct B : BaseState<> {
template <typename T>
void onExit() {};
};
int main() {
StateMachine<A, B> sm;
sm.activate<B>(); // A -> B
sm.activate<A>(); // Shouldn't switch state
}
onExit
member method allows me to perform some actions based on new state type.
I want to automatically deduce A and B template parameters based on onExit
specializations, so I do not need to manually specify all states that the certain state can transition to.
I was also thinking of moving template <typename T> void onExit() {}
definition to BaseState
class, however, It seems that you can't specialize inherited templated member methods.
As an alternative, I was thinking of returning boolean value from onExit
method, indicating whether the state should be transitioned, like so:
struct BaseState {};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool canTransition = std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
if (!canTransition) return false;
active.template emplace<T>();
return true;
}
};
struct B;
struct A : BaseState {
template <typename T>
bool onExit() { return false; }
template <>
bool onExit<B>() { std::cout << "A -> B" << std::endl; return true; }
};
struct B : BaseState {
template <typename T>
bool onExit() { return false; }
};
int main() {
StateMachine<A, B> sm;
sm.activate<B>(); // A -> B
sm.activate<A>(); // Shouldn't switch state
}
however, I don't really like the idea of specifying retval manually.
What are my options?
答案1
得分: 1
我理解了你的请求,以下是代码部分的翻译:
"Rather than deduce the pack Ts...
for your current BaseState
, you can use CRTP to check the existence of Current::onExit<Next>
within it.
template
struct BaseState {
template
bool transition () {
if constexpr (requires(S self) { self.template onExit
{
static_cast<S *>(this)->template onExit
return true;
}
return false;
}
};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool transitioned = std::visit([](auto&& arg) { return arg.template transition<T>(); }, active);
if (transitioned) {
active.template emplace<T>();
return true;
}
return false;
}
};
struct B;
struct A : BaseState {
template
requires std::same_as<T, B>
void onExit() { std::cout << "A -> B" << std::endl; }
};
struct B : BaseState {
};"
请注意,我只翻译了代码部分,没有包含问题的回答或其他内容。
英文:
Rather than deduce the pack Ts...
for your current BaseState
, you can use CRTP to check the existence of Current::onExit<Next>
within it.
template <typename S>
struct BaseState {
template <typename T>
bool transition () {
if constexpr (requires(S self) { self.template onExit<T>(); })
{
static_cast<S *>(this)->template onExit<T>();
return true;
}
return false;
}
};
template <typename... Ts>
struct StateMachine {
std::variant<Ts...> active;
template <typename T>
bool activate() {
const bool transitioned = std::visit([](auto&& arg) { return arg.template transition<T>(); }, active);
if (transitioned) {
active.template emplace<T>();
return true;
}
return false;
}
};
struct B;
struct A : BaseState<A> {
template <typename T>
requires std::same_as<T, B>
void onExit() { std::cout << "A -> B" << std::endl; }
};
struct B : BaseState<B> {
};
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论