Ограниченная функция шаблона никогда не вызывается

У меня есть две функции-члена шаблона, которые следует вызывать на основе соблюдения ограничения (полученного из определенного типа).

У меня есть шаблонная функция общего случая под названием addScheme, определенная следующим образом:

template <typename Field>
template <typename Scheme>
void TransportEquation<Field>::addScheme(Scheme&& scheme) {
    if (scheme.needsCorrection()) {
        _n_corrected_schemes++;
    }

    _schemes.emplace_back(std::make_shared<Scheme>(std::forward<Scheme>(scheme)));
}

Я добавил еще две функции для двух конкретных случаев.

Первая функция, с которой у меня нет проблем, тип шаблона Diffusion должен быть унаследован от IDiffusion:

template <typename Field>
template <typename Diffusion>
requires std::derived_from<Diffusion, IDiffusion>
void TransportEquation<Field>::addScheme(Diffusion&& diffusion) {
    if (diffusion.needsCorrection()) {
        _n_corrected_schemes++;
    }

    auto diff_scheme = std::make_shared<Diffusion>(std::forward<Diffusion>(diffusion));
    _diff_scheme = diff_scheme;
    _schemes.emplace_back(diff_scheme);
}

Моя проблема связана с другим, в котором схема должна быть получена из IConvection<G>, где G — другой тип шаблона:

template <typename Field>
template <typename Convection, typename G>
requires std::derived_from<Convection, scheme::convection::IConvection<G>>
void TransportEquation<Field>::addScheme(Convection&& convection) {
    if (convection.needsCorrection()) {
        _n_corrected_schemes++;
    }

    auto conv_scheme = std::make_shared<Convection>(std::forward<Convection>(convection));
    _conv_scheme = conv_scheme;
    _schemes.emplace_back(conv_scheme);
}

Эта функция никогда не вызывается, вместо нее всегда вызывается общая addScheme(Scheme&& scheme). Я не знаю, что не так с определением функции и почему ограничение никогда не выполняется?

Если будет полезно, то заявляю IConvection:

template <typename GradScheme = gradient::LeastSquares>
class IConvection {
// ...
};

и это производный тип, который никогда не соответствует ограничению addScheme(Convection&&) и вместо этого вызывается addScheme(Scheme&&):

template <typename G = gradient::LeastSquares>
class Upwind : public IConvection<G> {}

Приведите минимально воспроизводимый пример. Что-то, что можно напрямую скопировать/вставить и использовать для воспроизведения указанной проблемы/проблемы.

user12002570 09.08.2024 10:45

В частности, было бы полезно, если бы это был один фрагмент, который мы могли бы скопировать напрямую (без пропущенных заголовков или нескольких файлов).

HolyBlackCat 09.08.2024 10:47

@HolyBlackCat Я бы с удовольствием, но фрагменты являются частью большой базы кода. Можно ли опубликовать ссылку на GitHub в репозиторий?

Algo 09.08.2024 10:50

В вашем коде G невозможно вывести, поэтому шаблон нельзя вызвать.

n. m. could be an AI 09.08.2024 10:51

@n.m.couldbeanAI Спасибо, это тоже было мое первое предположение, но я не знаю, как сделать так, чтобы функция могла определить тип G.

Algo 09.08.2024 10:52

«Можно ли опубликовать ссылку на репозиторий на GitHub?» Нет, это ваша домашняя работа — сократить ее до меньшего примера. Это объяснено в ссылке первого комментария. Иногда люди замечают ошибку только глазами, но если ситуация сложнее, пример очень помогает.

HolyBlackCat 09.08.2024 10:56

Вывести G невозможно ни в какой форме. Вы можете добавить в templateIConvection поле типа подтипа using Its_a_IConvection = bool;, а затем обнаружить тот факт, что любой IConvection<B> имеет этот специальный подтип.

dalfaB 09.08.2024 11:00

Вы можете использовать черты is_template_base_of: requires is_template_base_of<scheme::convection::IConvection, Convection>::value.

Jarod42 09.08.2024 14:47

Вы можете получить IConvection<G> из какого-то нешаблонного (возможно, пустого) базового класса IConvectionBase и вместо этого проверить происхождение от него.

n. m. could be an AI 09.08.2024 16:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас нет ничего уточняющего G, поэтому оно не выводится, поэтому шаблон никогда не сопоставляется.

Вы можете добавить псевдоним типа к IConvection

template <typename GradScheme = gradient::LeastSquares>
class IConvection {
// ...
    public:
    using gradient_scheme = GradScheme;
};

А затем найдите это в разделе «Требования». Любой тип, у которого нет псевдонима типа gradient_scheme, не соответствует этому шаблону, это не серьезная ошибка.

template <typename Field>
template <typename Convection>
requires std::derived_from<Convection, scheme::convection::IConvection<typename Convection::gradient_scheme>>
void TransportEquation<Field>::addScheme(Convection&& convection);

Другие вопросы по теме