Declaring non-type template arguments with auto

suggest change

Prior to C++17, when writing a template non-type parameter, you had to specify its type first. So a common pattern became writing something like:

template <class T, T N>
struct integral_constant {
    using type = T;
    static constexpr T value = N;
};

using five = integral_constant<int, 5>;

But for complicated expressions, using something like this involves having to write decltype(expr), expr when instantiating templates. The solution is to simplify this idiom and simply allow auto:

template <auto N>
struct integral_constant {
    using type = decltype(N); 
    static constexpr type value = N;
};

using five = integral_constant<5>;

Empty custom deleter for std::unique_ptr

A nice motivating example can come from trying to combine the empty base optimization with a custom deleter for unique_ptr. Different C API deleters have different return types, but we don’t care - we just want something to work for any function:

template <auto DeleteFn>
struct FunctionDeleter {
    template <class T>
    void operator()(T* ptr) const {
        DeleteFn(ptr);
    }
};

template <T, auto DeleteFn>
using unique_ptr_deleter = std::unique_ptr<T, FunctionDeleter<DeleteFn>>;

And now you can simply use any function pointer that can take an argument of type T as a template non-type parameter, regardless of return type, and get a no-size overhead unique_ptr out of it:

unique_ptr_deleter<std::FILE, std::fclose> p;

Feedback about page:

Feedback:
Optional: your email if you want me to get back to you:


Templates:
* Declaring non-type template arguments with auto

Table Of Contents
8 Arrays
11 Loops
39 Streams
51 Unions
52 Templates
56 Lambdas
60 SFINAE
62 RAII
67 Sorting
84 RTTI
87 Scopes
104 Profiling
107 Recursion
117 Iteration
125 Alignment
134 Semaphore
136 Debugging
139 Mutexes
142 decltype