Advantages of auto in template parameters in C++17
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'> >;
auto' as a template argument placeholder for a function parameter
This syntax is valid in the C++ Concepts Technical Specification, but not in C++20. In C++20 concepts, auto
is only permitted at the top level in a function parameter type. The relevant rule is [dcl.spec.auto] paragraph 2:
A placeholder-type-specifier of the form type-constraint[opt]
auto
can be used as a decl-specifier of the decl-specifier-seq of a parameter-declaration of a function declaration or lambda-expression and, if it is not theauto
type-specifier introducing a trailing-return-type (see below), is a generic parameter type placeholder of the function declaration or lambda-expression. [Note: Having a generic parameter type placeholder signifies that the function is an abbreviated function template (9.3.3.5 [dcl.fct]) or the lambda is a generic lambda (7.5.5 [expr.prim.lambda]). —end note]
(If you check the wording in the most recent working draft at the time of writing, you will find a somewhat different rule. The above rule was modified by core issue 2447, which was voted into the C++20 final draft at the Prague committee meeting a week ago.)
The decl-specifiers in a function parameter are the initial sequence of keywords and type names at the start of the parameter declaration. The above rule allows auto
there at the top level:
void f(auto x);
... but only as a decl-specifier. auto
is not permitted when nested within a decl-specifier:
void f(std::vector<auto> x);
... and is also not permitted elsewhere in the parameter type:
void f(void (*p)(auto));
Use of auto in template parameters: Some usage examples and... how to make it work with constant size C arrays?
As far I know, you can't so simply.
As you can read in this page
Array and function types may be written in a template declaration, but they are automatically replaced by pointer to object and pointer to function as appropriate.
So you can write
template <auto a, typename TVal>
inline void fill_all(const TVal &v)
{ }
// ...
static int a[4] {};
fill_all<a>(2);
but fill_all()
see the type of a
as a int *
, not as int[4]
.
So you can use it as pointer but you have lost the information about the dimension.
The best I can imagine is call a constexpr
function that return the size of the array and put this value as template parameter (or function argument)
template <typename T, std::size_t N>
constexpr std::size_t getDim (T const (&)[N])
{ return N; }
template <auto a, std::size_t N, typename TVal>
inline void fill_all (TVal const & v)
{ std::fill(a, a + N, v); }
// ...
static int a[4] {};
fill_all<a, getDim(a)>(2);
but, unfortunately, I don't see a way to avoid the explicit call of getDim()
in the explicit template argument list.
Combining auto template parameters with std::optional, possible?
You could deduce what type of std::optional
you want from the function passed in.
Then you can return an empty optional if it throws.
#include <iostream>
#include <optional>
template <auto Func, typename E, typename ...Args>
auto safeCaller(Args&& ...args)
{
using ret = std::optional<decltype(Func(std::forward<Args>(args)...))>;
// this could even be wrapped in a loop for retrying
try
{
return ret{Func(std::forward<Args>(args)...)};
}
catch (E &e)
{
// ... perform some logging perhaps? or whatever else is relevant
return ret{};
}
}
int foo(std::string bar)
{
return bar.size();
}
int main()
{
// specialise safeCaller to work on foo and to expect std::runtime_error
auto result = safeCaller<foo, std::runtime_error>("baz");
if (result)
{
std::cout << *result << std::endl;
}
return 0;
}
Is There a Workaround for Visual Studio's Lack of Support for auto Template Parameters?
auto
non-type template parameters were introduced only in VS 2017 version 15.7.0.
Templates that are designed to take any type as a non-type parameter can now use the
auto
keyword in the template parameter list. This allows instantiations to use any type instead of needing to determine and supply the type of template parameter at the point of instantiation.
Before that version they are not supported.
c++ auto for type and nontype templates
Are there plans for such an extension in the next c++20 release?
No.
Is there some fundamental problem in having a syntax like
template<auto... X>
, withX
any type or nontype template parameter?
It would be a totally new concept in the language - having a name refer to either a type or a value in the same place. So it'd come with all sorts of additional questions - and probably additional language features to check if X
is a type or not.
The syntax likely cannot be template <auto... X> struct Y { };
since that syntax already has meaning and means a bunch of values and Y<int>{}
is ill-formed.
There are definitely places where such a thing would be useful though. A proposal would just have to address these issues.
How to enable auto nontype template parameter pack for same type of parameters
You can make use of the decltype
construct as shown below:
template<auto T1, decltype(T1)... Args> struct Custom
{
};
Working Demo
Related Topics
Implementing Comparison Operators Via 'Tuple' and 'Tie', a Good Idea
How to Take a Screenshot in a Windows Application
How Is Std::Function Implemented
C++ Function Template Partial Specialization
C++: Print Out Enum Value as Text
Why Do C and C++ Support Memberwise Assignment of Arrays Within Structs, But Not Generally
Replace Substring With Another Substring C++
Problem Sorting Using Member Function as Comparator
Double Precision - Decimal Places
What Does It Mean to Have an Undefined Reference to a Static Member
Deoptimizing a Program For the Pipeline in Intel Sandybridge-Family Cpus
Why Do We Need a Pure Virtual Destructor in C++
Generating Combinations in C++
Printing 1 to 1000 Without Loop or Conditionals
How to Pass a Member Function Pointer
Enforcing Statement Order in C++
Why Does Const Imply Internal Linkage in C++, When It Doesn't in C