Reputation: 1594
I have a function where I'd like the arguments partially-deduced and the remaining, mostly non-type arguments, are given by the user (as a way of enforcing them being given at compile-time). However, the type of this non-type user-sourced argument is deduced, therefor it must come before the user arguments. That breaks the ability of the user to have the first argument deduced. I have a small example below, that does not compile, demonstrating what I'm talking about.
template <typename T, T N>
class int_const {};
template <typename T, T M, T N>
auto add(int_const<T, N> a) {
return int_const<T, N + M>();
}
int main(void) {
int_const<int, 1> a;
add<32>(a);
// add<int, 32>(a); does compile, but requires the user to know or extract that first argument
return 0;
}
Is there anyway to support the template function call as it is seen in main()
?
Upvotes: 1
Views: 77
Reputation: 66230
If you can use C++17, you can use auto
for M
value
template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
return int_const<T, N + M>();
}
So you can call it as follows
add<32>(a);
Before C++17... well, I don't see a way without explicating also the type.
As pointed by Jarod42, auto M
intercept also values of different types.
If you want impose that the type of M
is exactly T
, you can use SFINAE; by example, as follows
template <auto M, typename T, T N,
std::enable_if_t<std::is_same_v<T, decltype(M)>, bool> = true>
auto add(int_const<T, N> a) {
return int_const<T, N + M>();
}
So you get errors from
add<32u>(a);
add<short{32}>(a);
But maybe you can relax the requirement and accept also that decltype(M)
isn't exactly T
but also simply that M
is narrowing convertible to T
.
Maybe
template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
return int_const<T, N + T{M}>();
} // .......................^^^^
so
add<32u>(a);
add<short{32}>(a);
are compiled because 32u
and short{32}
are narrowing convertible to int
where
add<(unsigned long)(-1)>(a);
gives a compilation error because (unsigned long)(-1)
(usually the bigger possible value for an unsigned long
) can't be narrowed to int
.
Upvotes: 2