Неоднозначная перегрузка на шаблонных вариационных шаблонах - PullRequest
9 голосов
/ 02 ноября 2011

Связано:


Рассмотрим эту пару шаблонов переменной:

template<typename Dummy>
bool All(Param& c) {
    return true;
}

template<typename Dummy, Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<Dummy, rest...>(c);
}

Это работаети компилирует.Однако, как написать это без первого параметра шаблона?

Звучит тривиально?Ну вот и я так думал.:-) Давайте рассмотрим некоторые идеи.

Идея № 1:

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}
template<>
bool All(Param& c) {
    return true;
}

Не сработает ... Когда я пытался это сделать, я имел в виду специализацию, но со второй мысли этоне так, как это работает.

В исходном примере я создал два разных шаблона перегрузок, сначала приняв 1 параметр шаблона, а затем 2 и более.Никаких двусмысленностей и никакой специализации. Я правильно понял?

Идея № 2:

bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

Очевидно, не сработает, All<rest...> с пустым rest... не расширитсяк вызову не шаблонной функции.

Идея # 3:

Давайте немного перестроим решение.

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

Это не пойдет,потому что все (с) было бы неоднозначным.Следовательно, мне нужно иметь случай 0-arg и случай> 0-arg ... Или как насчет случая 1-arg и случая> 1-arg?

Idea # 3.5:

template<Func* f>
bool All(Param& c) {
    return f(c);
}

template<Func* f, Func* f2, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<f2, rest...>(c);
}

Да, работает, но содержит copypasta (простой в данном случае, но может быть больше!), Поэтому я бы сказал, что это не лучше, чем я начал.Просто еще один обходной путь.

Идея № 4:

Давайте попробуем # 1, но с классами вместо функций.

template<Func* f, Func* ...rest>
struct All {
    static bool func(Param& c) {
        return f(c) && All<rest...>(c);
    }
};
template<>
struct All {
    static bool func(Param& c) {
        return true;
    }
};

Это выглядит многообещающе, так как я могу специализироваться на занятиях.Но эй, что это?

извините, не реализовано: не могу развернуть 'rest ...' в список аргументов фиксированной длины

Разве это не GCC4.4 вещь?Я нахожусь на MinGW GCC 4.6.1 (tdm-1).


В любом случае, должен ли я думать, что я не могу сделать такую ​​элементарную вещь простым способом?Требуется ли использовать обходной путь с дополнительным фиктивным параметром шаблона для выполнения этой задачи?

Или существует простой, правильный вариант для указания регистра с нулевым аргументом , который будет работать?

Ответы [ 2 ]

3 голосов
/ 02 ноября 2011

В этом вопросе, поскольку параметры шаблона не являются типами, если мы подготовим функцию с аргументом шаблона по умолчанию, как следующий параметр Dummy может быть сохранен:

template<typename = void>
bool All(Param& c) {
    return true;
}

template<Func* f, Func* ...rest>
bool All(Param& c) {
    return f(c) && All<rest...>(c);
}

Однако я не уверен, что это всегда применимо. Для более общего случая может потребоваться std::enable_if или аналогичная отправка (хотя это сделает код немного длиннее).

1 голос
/ 02 ноября 2011

Похоже, ваш вопрос похож на этот: Ошибка компиляции в функции рекурсивного вариационного шаблона

Есть два ответа, которые должны сработать; тот, который № 3,5, а второй - тот, которого у вас не было.

...