我有一个函数,我希望部分推导参数,而其余的(大多数是非类型的)参数由用户给出(作为在编译时给出它们的一种方式)。但是,推论出该非类型的用户源自变量的类型,因此它必须位于用户自变量之前。这破坏了用户推论第一个论点的能力。我在下面有一个小的示例,该示例无法编译,说明了我在说什么。
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;
}
在main()
中可以看到模板函数调用吗?
答案 0 :(得分:2)
如果可以使用C ++ 17,则可以将auto
的值用于M
template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
return int_const<T, N + M>();
}
因此您可以按以下方式调用它
add<32>(a);
在C ++ 17之前...好吧,我看不到一种不说明类型的方法。
正如Jarod42所指出的,auto M
还会拦截不同类型的值。
如果您想让M
的类型精确地 T
,则可以使用SFINAE;例如,如下
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>();
}
所以您会从
中得到错误add<32u>(a);
add<short{32}>(a);
但是也许您可以放宽要求,并接受decltype(M)
并不完全是T
,但也可以简单地认为M
可以转换为T
。
也许
template <auto M, typename T, T N>
auto add(int_const<T, N> a) {
return int_const<T, N + T{M}>();
} // .......................^^^^
如此
add<32u>(a);
add<short{32}>(a);
之所以进行编译是因为32u
和short{32}
的可转换范围缩小为int
,其中
add<(unsigned long)(-1)>(a);
出现编译错误,因为无法将(unsigned long)(-1)
(通常是unsigned long
的较大值)缩小到int
。