获取为其模板成员方法专门化的类型列表

huangapple go评论93阅读模式
英文:

Get list of types for which templated member method is specialized

问题

以下是您要翻译的代码部分:

  1. 我为我的FSM实现编写了以下基础代码
  2. template <typename... Ts>
  3. struct BaseState {
  4. template <typename T>
  5. static bool canTransition() {
  6. if constexpr((std::is_same_v<T, Ts> || ...)) return true;
  7. return false;
  8. }
  9. };
  10. template <typename... Ts>
  11. struct StateMachine {
  12. std::variant<Ts...> active;
  13. template <typename T>
  14. bool activate() {
  15. const bool canTransition = std::visit([](auto&& arg) { return arg.template canTransition<T>(); }, active);
  16. if (!canTransition) return false;
  17. std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
  18. active.template emplace<T>();
  19. return true;
  20. }
  21. };
  22. struct B;
  23. struct A : BaseState<B> {
  24. template <typename T>
  25. void onExit() {}
  26. template <>
  27. void onExit<B>() { std::cout << "A -> B" << std::endl; }
  28. };
  29. struct B : BaseState<> {
  30. template <typename T>
  31. void onExit() {};
  32. };
  33. int main() {
  34. StateMachine<A, B> sm;
  35. sm.activate<B>(); // A -> B
  36. sm.activate<A>(); // 不应该切换状态
  37. }
  38. 'onExit'成员方法允许我基于新状态类型执行一些操作。
  39. 我希望根据'onExit'的特化自动推断AB的模板参数,这样我就不需要手动指定所有状态可以过渡到的特定状态。
  40. 我还考虑将'template <typename T> void onExit() {}'的定义移动到'BaseState'类中,但是似乎不能专门化继承的模板成员方法。
  41. 作为替代方案,我考虑从'onExit'方法中返回布尔值,指示是否应转换状态,如下所示:
  42. struct BaseState {};
  43. template <typename... Ts>
  44. struct StateMachine {
  45. std::variant<Ts...> active;
  46. template <typename T>
  47. bool activate() {
  48. const bool canTransition = std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
  49. if (!canTransition) return false;
  50. active.template emplace<T>();
  51. return true;
  52. }
  53. };
  54. struct B;
  55. struct A : BaseState {
  56. template <typename T>
  57. bool onExit() { return false; }
  58. template <>
  59. bool onExit<B>() { std::cout << "A -> B" << std::endl; return true; }
  60. };
  61. struct B : BaseState {
  62. template <typename T>
  63. bool onExit() { return false; }
  64. };
  65. int main() {
  66. StateMachine<A, B> sm;
  67. sm.activate<B>(); // A -> B
  68. sm.activate<A>(); // 不应切换状态
  69. }
  70. 然而,我不太喜欢手动指定返回值的想法。
  71. 我有哪些选择?
英文:

I wrote a following base code for my FSM implementation:

  1. template <typename... Ts>
  2. struct BaseState {
  3. template <typename T>
  4. static bool canTransition() {
  5. if constexpr((std::is_same_v<T, Ts> || ...)) return true;
  6. return false;
  7. }
  8. };
  9. template <typename... Ts>
  10. struct StateMachine {
  11. std::variant<Ts...> active;
  12. template <typename T>
  13. bool activate() {
  14. const bool canTransition = std::visit([](auto&& arg) { return arg.template canTransition<T>(); }, active);
  15. if (!canTransition) return false;
  16. std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
  17. active.template emplace<T>();
  18. return true;
  19. }
  20. };
  21. struct B;
  22. struct A : BaseState<B> {
  23. template <typename T>
  24. void onExit() {}
  25. template <>
  26. void onExit<B>() { std::cout << "A -> B" << std::endl; }
  27. };
  28. struct B : BaseState<> {
  29. template <typename T>
  30. void onExit() {};
  31. };
  32. int main() {
  33. StateMachine<A, B> sm;
  34. sm.activate<B>(); // A -> B
  35. sm.activate<A>(); // Shouldn't switch state
  36. }

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:

  1. struct BaseState {};
  2. template <typename... Ts>
  3. struct StateMachine {
  4. std::variant<Ts...> active;
  5. template <typename T>
  6. bool activate() {
  7. const bool canTransition = std::visit([](auto&& arg) { return arg.template onExit<T>(); }, active);
  8. if (!canTransition) return false;
  9. active.template emplace<T>();
  10. return true;
  11. }
  12. };
  13. struct B;
  14. struct A : BaseState {
  15. template <typename T>
  16. bool onExit() { return false; }
  17. template <>
  18. bool onExit<B>() { std::cout << "A -> B" << std::endl; return true; }
  19. };
  20. struct B : BaseState {
  21. template <typename T>
  22. bool onExit() { return false; }
  23. };
  24. int main() {
  25. StateMachine<A, B> sm;
  26. sm.activate<B>(); // A -> B
  27. sm.activate<A>(); // Shouldn't switch state
  28. }

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;

  1. template <typename T>
  2. bool activate() {
  3. const bool transitioned = std::visit([](auto&& arg) { return arg.template transition<T>(); }, active);
  4. if (transitioned) {
  5. active.template emplace<T>();
  6. return true;
  7. }
  8. return false;
  9. }

};

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&lt;Next&gt; within it.

  1. template &lt;typename S&gt;
  2. struct BaseState {
  3. template &lt;typename T&gt;
  4. bool transition () {
  5. if constexpr (requires(S self) { self.template onExit&lt;T&gt;(); })
  6. {
  7. static_cast&lt;S *&gt;(this)-&gt;template onExit&lt;T&gt;();
  8. return true;
  9. }
  10. return false;
  11. }
  12. };
  13. template &lt;typename... Ts&gt;
  14. struct StateMachine {
  15. std::variant&lt;Ts...&gt; active;
  16. template &lt;typename T&gt;
  17. bool activate() {
  18. const bool transitioned = std::visit([](auto&amp;&amp; arg) { return arg.template transition&lt;T&gt;(); }, active);
  19. if (transitioned) {
  20. active.template emplace&lt;T&gt;();
  21. return true;
  22. }
  23. return false;
  24. }
  25. };
  26. struct B;
  27. struct A : BaseState&lt;A&gt; {
  28. template &lt;typename T&gt;
  29. requires std::same_as&lt;T, B&gt;
  30. void onExit() { std::cout &lt;&lt; &quot;A -&gt; B&quot; &lt;&lt; std::endl; }
  31. };
  32. struct B : BaseState&lt;B&gt; {
  33. };

huangapple
  • 本文由 发表于 2023年5月11日 17:28:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76226123.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定