Що таке посібники з вирахування шаблонів і коли ми повинні ними користуватися?


87

Стандарт C ++ 17 вводить "посібники з вирахування шаблонів". Я вважаю, що вони мають щось спільне з новим вирахуванням аргументу шаблону для конструкторів, представленим у цій версії стандарту, але я ще не бачив простого пояснення щодо того, для чого вони потрібні, у стилі поширених запитань.

  • Що таке посібники з вирахування шаблонів у C ++ 17?

  • Навіщо (і коли) вони нам потрібні?

  • Як їх заявити?



Зокрема, мені було б цікаво дізнатися, чи дійсно будь-які напрямки відрахувань надаються C ++ 17 STL (наприклад, для std :: pair або std :: tuple). Який повний перелік стандартних типів шаблонів, що можна визначити, станом на C ++ 17?
Quuxplusone


Мені було б цікаво дізнатись, чи підтримує це якийсь компілятор. Я спробував gcc, clang та vc ++. rextester.com/DHPHC32332 Неважливо , я виявив, що він працює лише з gc ++ 8.1 C ++ 17 та 2a g ++ -std = c ++ 17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
Jean-Simon кину

Відповіді:


98

Посібники виведення шаблону - це шаблони, пов'язані з класом шаблону, які повідомляють компілятору, як перевести набір аргументів конструктора (та їх типи) у параметри шаблону для класу.

Найпростіший приклад - це std::vectorта його конструктор, який бере пару ітераторів.

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

Компілятор повинен зрозуміти, що vector<T>«s 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спеціалізацію, використовуючи код праворуч від ->.

Вам потрібні вказівки, коли відрахування типу з аргументів не базується на типі одного з цих аргументів. Ініціалізація a vectorз initializer_listявно використовує vector's T, тому йому не потрібен посібник.

Ліва сторона не обов'язково вказує фактичний конструктор. Це працює так, що якщо ви використовуєте відрахування конструктора шаблону для типу, він збігається з аргументами, які ви передаєте проти всіх напрямків відрахувань (фактичні конструктори первинного шаблону надають неявні напрямні). Якщо є збіг, він використовує це, щоб визначити, які аргументи шаблону надати типу.

Але як тільки це вирахування буде зроблено, як тільки компілятор з’ясує параметри шаблону для типу, ініціалізація для об’єкта цього типу триває так, ніби нічого з цього не сталося. Тобто обраний напрямок відрахування не повинен відповідати вибраному конструктору .

Це також означає, що ви можете використовувати напрямні з агрегатами та ініціалізацією агрегатів:

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

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

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

Отже, напрямки відрахувань використовуються лише для з’ясування типу, який ініціалізується. Фактичний процес ініціалізації працює точно так само, як і раніше, як тільки це було зроблено.


7
Хм, мені просто спало на думку, що навіть з гідом vector v{first, last};не вчинитиме належного :(
TC

3
@TC ... якщо тільки правильно не робить вектор ітераторів. І std::string{32,'*'}[0] == ' '(для ASCII). Але все це було вірно з моменту C ++ 11.
Арне Фогель

2
що відбувається з векторним параметром розподільника? що могло б статися, якби у векторному параметрі розподільника не було аргументу за замовчуванням? (ви не можете вивести це з InputIterator)
gnzlbg

@NicolBolas: Чи не могли б Ви пояснити деталі того, як неявні та явні посібники з відрахування можуть працювати в контексті частково або повністю спеціалізованих класів (конструктори яких явно не повинні мати типів параметрів, що відповідають типовим основного шаблону)? Швидким пошуком важко знайти інформацію про це.
user541686

1
@NicolBolas: Розумію. Мені незрозуміло, що питання взагалі стосується явних керівництв про відрахування ... Я вважаю корисним, якщо ви просто включите те, що буквально написали до цього коментаря.
користувач541686
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.