Ветвь поведения времени компиляции на основе производного типа - PullRequest
0 голосов
/ 30 августа 2018

У меня есть пара классов 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);
}

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Вы не можете сделать это во время компиляции, поскольку фактический параметр, заданный для функции и ее оценки, может происходить только во время выполнения.

Вместо этого вы можете переместить отношения между типами во время компиляции, может быть, вы можете прочитать о 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
    //...
}
0 голосов
/ 30 августа 2018

И func_1, и func_2 должны быть шаблонизированы, возможно, с помощью некоторого SFINAE, чтобы убедиться, что вызывающие типы получены из S. Затем вы просто делаете if constexpr(std::is_same<std::decay_t<T>, FS>::value) и реализуете различное поведение для разных классов.
Если вы передадите указатель базового класса в метод, то я считаю, что нет способа извлечь производный тип во время компиляции.

...