Что такое руководства по вычитанию шаблонов и когда мы должны их использовать?

В стандарте С++ 17 представлены "руководства по вычитанию шаблонов". Я понимаю, что они как-то связаны с выводом аргумента нового шаблона для конструкторов, представленным в этой версии стандарта, но я еще не видел простого, часто заданного в FAQ объяснения того, что это такое и для чего он предназначен.

  • Что такое руководства по вычитанию шаблонов в С++ 17?

  • Почему (и когда) они нам нужны?

  • Как объявить их?

+56
источник поделиться
2 ответа

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

Самый простой пример - это std::vector и его конструктор, который принимает пару итераторов.

template<typename Iterator>
void func(Iterator first, Iterator last)
{
  vector v(first, last);
}

Компилятор должен выяснить, какой будет vector<T> T Мы знаем, что такое ответ; T должен быть typename std::iterator_traits<Iterator>::value_type. Но как мы можем сообщить компилятору, не vector<typename std::iterator_traits<Iterator>::value_type>?

Вы используете руководство по вычету:

template<typename Iterator> vector(Iterator b, Iterator e) -> 
    vector<typename std::iterator_traits<Iterator>::value_type>;

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

Вам нужны справочники, когда вывод типа из аргументов не основан на типе одного из этих аргументов. Инициализация vector из initializer_list явно использует vector T, поэтому он не нуждается в руководстве.

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

Но как только этот вывод будет выполнен, как только компилятор выберет параметры шаблона для типа, инициализация объекта этого типа происходит так, как будто ничего из этого не произошло. То есть, выбранное руководство вычитания не должно соответствовать выбранному конструктору.

Это также означает, что вы можете использовать руководства с агрегатами и агрегатной инициализацией:

template<typename T>
struct Thingy
{
  T t;
};

Thingy(const char *) -> Thingy<std::string>;

Thingy thing{"A String"}; //thing.t is a 'std::string'.

Поэтому руководства по вычитанию используются только для определения инициализированного типа. Фактический процесс инициализации работает точно так же, как и раньше, как только это определение было сделано.

+58
источник

Вот пример использования руководства по вычету, который я использовал для упрощения построения объектов-прокси в шаблоне прокси. Надеюсь, что это может дать вам некоторые идеи простейших вещей, которые мы можем сделать с помощью прокси-шаблона с использованием современных c++. Руководства по дедукции, которые я использовал:

ProxyContainer(vector<string>&) -> ProxyContainer<<vector<string>, string>;

ProxyContainer(int*) -> ProxyContainer<<vector<int>, int>;
-3
источник

Связанные вопросы


Похожие вопросы

Посмотрите другие вопросы по меткам или Задайте вопрос