C++ 基于派生类型的编译时行为分支

C++ 基于派生类型的编译时行为分支,c++,polymorphism,c++17,template-meta-programming,C++,Polymorphism,C++17,Template Meta Programming,我有一对类FS和DS,它们都是从另一个类S派生的。我有一个函数,我在其中传递一个S*(即FS或DS),它进一步调用传递相同S*的另一个函数。在最后一个函数中,我需要根据S是FS还是DS有不同的行为,但更愿意在编译时解析这个分支,因为它位于关键路径上。我怎样才能做到这一点?一些涉及元编程和/或constexpr的东西,我觉得-我不想每次都进行虚拟调用 为简洁起见,省略了无关的细节 class S {}; class FS : public S {}; class DS : public S {};

我有一对类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);
}

func_1
func_2
都应该模板化,可能需要使用一些SFINAE来确保调用类型是从S派生的。如果constepr(std::is_same::value)并为不同的类实现不同的行为,则只需执行


如果将基类指针传递给该方法,则我认为无法在编译时检索派生类型。

您不能在编译时执行此操作,因为给定给函数的实际参数及其求值只能在运行时进行

您可以做的是将类型之间的关系移动到编译时,也许您可以了解这种奇怪的循环模板模式

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
    //...
}
模板
结构S{};
结构DS:S{};
模板
无效函数(Sconst&s)
{
如果constexpr(std::is_same::value)
//...
其他的
//...
}

如果您不知道将使用哪个具体实例(FS或DS)调用函数,则无论是否使用模板,都无法实现这种编译时多态性。你要么切换它,要么使用虚拟调用。关于这种类型的模板元编程,请参见这里的总结答案:这个问题很不清楚。此关键路径是否多次运行?像是在循环中?那么“pass”指的是循环还是什么?它是否在同一对象或同一类型的对象上重复运行?一个是必需的,其中它是最小的,并且显示问题。@Yakk AdamNevraumont显然不清楚,或者在这种情况下需要一个MVP,考虑到5个不同的用户都在您之前7小时以或多或少相同的答案回答posted@Madden我能想出十几个答案,这些答案与前面给出的答案不同。他们为你的问题可能涉及的一个问题提供了一个可能的答案。是关于它的吗?大概问题还不清楚。不清楚的问题会得到答案,但并不意味着它们就是真正问题的答案。好主意,我已经在为另一个类家族使用CRTP,但希望在不使用它的情况下解决当前的问题,而不是使用
模板void func
,然后
如果constexpr(std::is_same{})
可以使用简单的重载:
void func(S)
void func(S)
。此外,我猜您的意思是编写
结构DS:S{。我的。