需要在用户参数之前*推导参数的模板参数

时间:2019-01-29 03:29:27

标签: c++ templates template-deduction

我有一个函数,我希望部分推导参数,而其余的(大多数是非类型的)参数由用户给出(作为在编译时给出它们的一种方式)。但是,推论出该非类型的用户源自变量的类型,因此它必须位于用户自变量之前。这破坏了用户推论第一个论点的能力。我在下面有一个小的示例,该示例无法编译,说明了我在说什么。

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()中可以看到模板函数调用吗?

1 个答案:

答案 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);

之所以进行编译是因为32ushort{32}的可转换范围缩小为int,其中

add<(unsigned long)(-1)>(a);

出现编译错误,因为无法将(unsigned long)(-1)(通常是unsigned long的较大值)缩小到int