Выведение аргументов шаблона частичного класса в C ++ 17

В приведенном ниже примере мы используем функцию C ++ 17 «Вывод аргументов шаблона класса», чтобы сделать вывод, что val имеет тип Base<int, double, bool>:

template<class T, class U, class V>
struct Base {
    Base(T, U) { };
    Base(T, U, V) { };
    Base(V) { };
};

void func() {
    Base val(1, 4., false);
}

Теперь можно частично указать аргументы шаблона и позволить вывести оставшиеся? Фактически что-то вроде:

Base<V = bool> val1(1, 4.);        // U & V deduced --> Base<int, double, bool>
Base<T = bool, T = int> val2(5.);  // V deduced     --> Base<bool, int, double>

Я пробовал, например,

template<class T, class U> using Base2 = Base<T, U, double>;

void func() {
    NewBase2 val(1, 2);
}

но он не компилируется: 'Base2': use of alias template requires template argument list.

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


person Phil-ZXX    schedule 19.08.2019    source источник
comment
В приведенном примере вы можете указать T и получить U и получить V, или указать T и U и получить V. Видите узор? Было бы неплохо иметь именованные параметры шаблона в C ++, но, к сожалению, мы этого не делаем.   -  person Sam Varshavchik    schedule 19.08.2019


Ответы (2)


Вы можете добавить следующую инструкцию по дедукции:

template<class T, class U, class V>
Base(T, U) -> Base<T, U, bool>;

template<class V>
Base(V) -> Base<bool, int, V>;

который позволяет

Base val1(1, 4.); // Base<int, double, bool>
Base val2(5.);    // Base<bool, int, double>

Если вы хотите указать шаблон "по умолчанию", вы можете использовать старый способ с make_

template <typename V, typename T, typename U>
Base<T, U, V> make_Base(T t, U u)
{
    return Base<T, U, V>{t, u};
}

template <typename T, typename U, typename V>
Base<T, U, V> make_Base(V v)
{
    return Base<T, U, V>{v};
}


auto val1 = make_Base<bool>(1, 4.);   // Base<int, double, bool>
auto val2 = make_Base<bool, int>(5.); // Base<bool, int, double>
person Jarod42    schedule 19.08.2019

CTAD (выведение аргументов из шаблона классов) в настоящее время представляет собой процесс «все или ничего». Вы либо ничего не указываете и позволяете компилятору выводить все аргументы, либо указываете все аргументы, выводя компилятор из цикла.

Есть статья (P1021R0 ), который просит об этом и многом другом, но он еще не принят. Была статья с просьбой о частичной специализации, но после исправлений она была удалена. Последняя версия по-прежнему включает предложение чтобы иметь функцию CTAD при использовании псевдонима.


Per @ Барри Поддержка шаблонов псевдонимов (P1814) и агрегаты (P1816) были добавлены в рабочий проект для C ++. 20. Не добавлена ​​поддержка частичного CTAD или CTAD с унаследованными конструкторами.

person NathanOliver    schedule 19.08.2019
comment
Последней редакцией документа является P1021, который был разделен на два разных документа: P1814 для шаблонов псевдонимов и P1816 для агрегатов. Оба они были добавлены в рабочий проект для C ++ 20. Не будет ни частичного CTAD, ни поддержки унаследованных конструкторов. - person Barry; 19.08.2019
comment
@Barry Спасибо за источники. Я добавлю это. - person NathanOliver; 19.08.2019