74

What are the advantages of auto in template parameters that will (possibly) be introduced with C++17?

Is it just a natural extension of auto when I want to instantiate template code?

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

What else do I gain from this language feature?

Damian
  • 4,395
  • 4
  • 39
  • 67
  • 4
    As additional Information [Declaring non-type template arguments with auto](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0127r1.html) – t.niese Jun 25 '16 at 10:56
  • 18
    Every now and then I see questions like [this one](http://stackoverflow.com/questions/24185315/passing-any-function-as-template-parameter) or [this one](http://stackoverflow.com/questions/37232082/how-to-make-template-parameter) or [this one](http://stackoverflow.com/questions/33049706/passing-pointer-to-any-member-function-as-class-template-argument) on StackOverflow. `template < auto >` will make these askers happy. – cpplearner Jun 25 '16 at 12:36
  • I thought the main thins was `std::vector v{1,2,3,4,5};` and difficult things like callable types as template args (esp lambdas). – emsr Jun 26 '16 at 19:08
  • @emsr: No, that's not what it does. The `auto` goes on the definition, not the point of use. – Nicol Bolas Jun 26 '16 at 21:48
  • @emsr that's a separate feature that's part of the Concepts TS, but not in C++17. The p0127 use of `auto` does not conflict with it though. – Jonathan Wakely Jul 29 '16 at 12:29

4 Answers4

96

The template <auto> feature (P0127R1) was accepted into C++ in the ISO C++ 2016 meeting in Oulu, Finland.

An auto keyword in a template parameter can be used to indicate a non-type parameter the type of which is deduced at the point of instantiation. It helps to think of this as a more convenient way of writing:

template <typename Type, Type value>

For example,

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

can now be written as

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

where you don't need to explicitly spell out the type any more. P0127R1 also includes some simple but good examples where using template <auto> with variadic template parameters is very handy, for example for implementations of compile-time lists constant values:

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>;

In pre-C++1z, while HomogenousValueList could be simply written as

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

writing an equivalent of HeterogenousValueList would not be possible without wrapping the values in some other templates, for example:

template <typename ... ValueTypes> struct Cxx14HeterogenousValueList {};
using MyList4 = Cxx14HeterogenousValueList<constant<int, 42>,
                                           constant<char, 'X'> >;
mceo
  • 1,221
  • 11
  • 18
  • non-type template parameters can't be anything so something like constant<3.0> doesn't work. So much for generic code. – jondoe Sep 13 '19 at 16:56
  • @jondoe One potential workaround would be to use `std::ratio` in place of floating-point values and convert them to actual floating-point values later when needed. – mceo Sep 15 '19 at 07:16
  • 3
    @jondoe: C++20 does allow floating-point template parameters. – Davis Herring Feb 23 '20 at 02:28
  • 1
    In your last example `constant` is a value, thus it cannot be passed to a `typename`. – Dr. Gut Nov 07 '20 at 22:22
14

Actually, the case of real values in mceo's (original) answer is explicitly not covered as non-type template parameter.

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

See the example given in the mentioned proposal: Modify §14.3.2 paragraph 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

Just stumbled over the same misconception myself a few days ago.

Neil
  • 14,063
  • 3
  • 30
  • 51
m-j-w
  • 262
  • 1
  • 5
  • 2
    While this is nice to know, and upvoted, by now I don't see how it's relevant to the question. Nobody is now suggesting real values can be used as non-type template parameters. – einpoklum Mar 16 '17 at 21:08
  • 2
    This was an answer to the original answer of mceo, where he gave an example of a real value as template argument, which, however, is not permitted. This aspect is now included in the accepted answer above after being edited, and is now essentially redundant. – m-j-w Mar 17 '17 at 00:01
  • 4
    And it is relevant to the question in the sense that the introduction of 'auto' did not sneak in new template argument types as one can easily get the impression of. – m-j-w Mar 17 '17 at 00:07
  • 3
    FYI, in C++20, floating-point values are allowed as template parameters. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1714r1.html – jorgbrown Feb 09 '21 at 00:23
7

Here is another example (originally presented by @Rakete1111 as an answer for template template parameter of unknown type):

Extracting the value of SIZE without knowing its type:

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;
}
Amir Kirsh
  • 12,564
  • 41
  • 74
  • Concerning `C++17`, is `auto` in this context constrained to the set of types of a non-type template parameter? – 303 Jan 05 '22 at 03:09
  • Can you please explain how this works? – Alex O Feb 23 '23 at 02:13
  • @AlexO We are captueing K as a template template parameter. Same as typename for template says "any type, compiler please deduce" the auto for the inner template parameter says "any type of value" which helps here as the inner template parameter is a non-type. – Amir Kirsh Feb 23 '23 at 14:09
6

C++20 seemed to add another usage

... but it doesn't :-(

The concepts technical specification allowed a function parameter with auto template argument placeholder, e.g.:

void printPair(const std::pair<auto, auto>& p) {
    std::cout << p.first << ", " << p.second << std::endl;
}

But it was removed later in the C++20 specification.

This is a neat usage... I am hoping it will get in again in C++26!

See: 'auto' as a template argument placeholder for a function parameter

Amir Kirsh
  • 12,564
  • 41
  • 74
  • Yeah this simplifies a lot of boilerplate, i want this too. GCC compiles this, Clang refuses. – 0xB00B Nov 13 '22 at 05:34