Преимущества авто в параметрах шаблона в С++ 17

Каковы преимущества auto в параметрах шаблона, которые будут (возможно) введены с С++ 17?

Является ли это просто естественным расширением auto, когда я хочу создать экземпляр кода шаблона?

auto v1 = constant<5>;      // v1 == 5, decltype(v1) is int
auto v2 = constant<true>;   // v2 == true, decltype(v2) is bool
auto v3 = constant<'a'>;    // v3 == 'a', decltype(v3) is char

Что еще я получу от этой языковой функции?

Ответы

Ответ 1

Функция template <auto> (P0127R1) была принята на С++ на собрании ISO С++ 2016 в Оулу, Финляндия.

Ключевое слово auto в параметре шаблона может использоваться для указания параметра non-type, тип которого выведен в момент создания. Это помогает думать об этом как о удобном способе написания:

template <typename Type, Type value>

Например,

template <typename Type, Type value> constexpr Type constant = value;
constexpr auto const IntConstant42 = constant<int, 42>;

теперь можно записать как

template <auto value> constexpr auto constant = value;
constexpr auto const IntConstant42 = constant<42>;

где вам больше не нужно явно указывать тип. P0127R1 также содержит некоторые простые, но хорошие примеры, где использование template <auto> с параметрами вариационного шаблона очень удобно, например, для реализаций времени компиляции перечисляет постоянные значения:

template <auto ... vs> struct HeterogenousValueList {};
using MyList1 = HeterogenousValueList<42, 'X', 13u>;

template <auto v0, decltype(v0) ... vs> struct HomogenousValueList {};
using MyList2 = HomogenousValueList<1, 2, 3>;

В pre-С++ 1z, а HomogenousValueList можно просто написать как

template <typename T, T ... vs> struct Cxx14HomogenousValueList {};
using MyList3 = Cxx14HomogenousValueList<int, 1, 2, 3>;

запись эквивалента HeterogenousValueList невозможна без обертывания значений в некоторых других шаблонах, например:

template <typename ... ValueTypes> struct Cxx14HeterogenousValueList {};
using MyList4 = Cxx14HeterogenousValueList<constant<int, 42>,
                                           constant<char, 'X'> >;

Ответ 2

Фактически, случай реальных значений в mceo (исходном) ответе явно не рассматривается как параметр непигового шаблона.

template <auto ... vs> struct HeterogenousValueList {};
using MyList1 = HeterogenousValueList<42, 'X', 1.3f>;

См. пример, приведенный в упомянутом предложении: Измените пункт §14.3.2, пункт 2:

template<auto n> struct B { /* ... */ };
B<5> b1;   // OK: template parameter type is int
B<'a'> b2; // OK: template parameter type is char
B<2.5> b3; // error: template parameter type cannot be double

Просто наткнулся на то же заблуждение себя несколько дней назад.

Ответ 3

Вот еще один пример (первоначально представленный @Rakete1111 в качестве ответа для параметра шаблона шаблона неизвестного типа):

Извлечение значения SIZE, не зная его типа:

template<std::size_t SIZE>
class Foo {};

template <template<auto> class T, auto K>
auto extractSize(const T<K>&) {
    return K;
}

int main() {
    Foo<6> f1;
    Foo<13> f2;
    std::cout << extractSize(f1) << std::endl;
    std::cout << extractSize(f2) << std::endl;
}