【问题标题】:Compile time behaviour branch based on derived type基于派生类型的编译时行为分支
【发布时间】:2019-02-05 06:07:12
【问题描述】:

我有一对类 FS 和 DS,它们都派生自另一个类 S。我有一个函数,我传入一个 S*(即 FS 或 DS),它进一步调用另一个传入同一个 S 的函数*。在这个最终函数中,我需要根据 S 是 FS 还是 DS 有不同的行为,但由于它位于关键路径上,我更愿意在编译时解析这个分支。我怎样才能做到这一点?我觉得涉及元编程和/或 constexpr 的东西 - 我不想每次都进行虚拟调用

为简洁起见省略了无关的细节

class S {};
class FS : public S {};
class DS : public S {};

void func_2(Space *s) {
     // common code
     // branch based on lowest type of s
     // common code
}

void func_1(Space *s) {
    // common code
    func_2(s);
}

【问题讨论】:

  • 如果您不知道函数将使用哪个具体实例(FS 或 DS)被调用,那么无论有没有模板,您都无法实现这种类型的编译时多态性。您要么必须切换它,要么确实使用虚拟呼叫。
  • 有关此类模板元编程的总结答案请参见此处:stackoverflow.com/a/1881730/2754173
  • 这个问题很不清楚。这条关键路径是否不止一次运行?像循环一样?那么“通过”是指循环还是什么?它是否在同一对象或对象类型上重复运行? minimal reproducible example 是必需的,它最小并且显示问题
  • @Yakk-AdamNevraumont 考虑到 5 个不同的用户在您发帖前 7 小时都回答了或多或少相同的答案,显然不清楚或在这种情况下需要 MVP
  • @Madden 我能想到十几个与提出的不同的答案。他们为您的问题可能涉及的一个可能问题提供了一种可能的答案。是关于它吗?可能是。问题不清楚。不清楚的问题得到答案,并不意味着它们就是真正问题的答案。

标签: c++ polymorphism c++17 template-meta-programming


【解决方案1】:

func_1func_2 都应该被模板化,可能使用一些 SFINAE 来确保调用类型是从 S 派生的。然后你只需执行 if constexpr(std::is_same<std::decay_t<T>, FS>::value) 并为不同的类实现不同的行为。
如果将基类指针传递给方法,那么我相信没有办法在编译时检索派生类型。

【讨论】:

    【解决方案2】:

    你不能在编译时这样做,因为给函数的实际参数和它的评估只能在运行时发生。

    您可以做的是将类型之间的关系转移到编译时,也许您可​​以阅读 Curiously recurring Template Pattern。

    template <typename ActualType>
    struct S  {};
    
    struct DS:S<DS> {};
    
    template <typename ActualType>
    void func(S<ActualType>const& s)
    {
        if constexpr(std::is_same<ActualType, DS>::value)
        //...
        else
        //...
    }
    

    【讨论】:

    • 好主意,我已经将 CRTP 用于另一个类,但希望没有它来解决当前的问题
    • 你可以使用简单的重载来代替template&lt;class ActualType&gt; void func(S&lt;ActualType&gt;)if constexpr(std::is_same&lt;ActualType, DS&gt;{})void func(S&lt;DS&gt;)void func(S&lt;FS&gt;)
    • 另外,我猜你的意思是写struct DS : S&lt;DS&gt; {};。我的edit has been rejected
    猜你喜欢
    • 1970-01-01
    • 2017-09-28
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 2022-10-14
    相关资源
    最近更新 更多