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

Template parameters that require deduced argument *before* user arguments

我有一个函数,我希望其中的参数被部分推导出来,而其余的(主要是非类型参数)由用户提供(作为强制在编译时提供它们的一种方式)。然而,这个非类型用户来源参数的类型是推导出来的,因此它必须在用户参数之前。这打破了用户推导出第一个参数的能力。我在下面有一个小例子,它没有编译,展示了我在说什么。

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,就可以用autoM

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.