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

Template parameters that require deduced argument *before* user arguments

本文关键字:参数 用户 需要      更新时间:2023-10-16

我有一个函数,我希望参数部分推导,其余的,主要是非类型参数,由用户给出(作为在编译时强制执行它们的一种方式)。但是,推导出此非类型用户源参数的类型,因此它必须位于用户参数之前。这破坏了用户推导第一个参数的能力。我在下面有一个小例子,它没有编译,演示了我在说什么。

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

如果可以使用 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