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

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

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

template &lt;typename S&gt;
struct BaseState {
template &lt;typename T&gt;
bool transition () {
if constexpr (requires(S self) { self.template onExit&lt;T&gt;(); })
{
static_cast&lt;S *&gt;(this)-&gt;template onExit&lt;T&gt;();
return true;
}
return false;
}
};
template &lt;typename... Ts&gt;
struct StateMachine {
std::variant&lt;Ts...&gt; active;
template &lt;typename T&gt;
bool activate() {
const bool transitioned = std::visit([](auto&amp;&amp; arg) { return arg.template transition&lt;T&gt;(); }, active);
if (transitioned) {
active.template emplace&lt;T&gt;();    
return true;
}
return false;
}
};
struct B;
struct A : BaseState&lt;A&gt; {
template &lt;typename T&gt;
requires std::same_as&lt;T, B&gt;
void onExit() { std::cout &lt;&lt; &quot;A -&gt; B&quot; &lt;&lt; std::endl; }
};
struct B : BaseState&lt;B&gt; {
};

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:

确定