跨多个参数的统一模板推导

时间:2019-06-04 23:12:15

标签: templates c++17 template-deduction argument-deduction

我想看看是否有可能(尽管我感觉不是)是否可以基于给定的第一个模板参数来应用统一类型。例如:

template <class T>
void foo(T, T) {}

int main() {
  // deduced as int
  foo(1, 1);

  // deduced as double
  foo(1.0, 1.0);

  // not deducible, will error.
  //foo(1.0, 1);

  return 0;
}

是否有某种技术可以让我强制foo的第二个参数恰好是第一个?我确实意识到,尽管较为冗长,但规范的解决方案是foo<double>(1.0, 1)

话虽这么说,我希望能够执行foo(1.0, 1),它将第二个参数类型强制为第一个,并将1转换为1.0。

另外,foo(1, 1.0)会失败,因为第一个参数将foo设置为foo<int>,因此第二个参数不能向下转换为整数。

最后,我希望能够在不进行递归模板化的情况下执行此操作,因为我想将此技术应用于对象构造函数。

1 个答案:

答案 0 :(得分:3)

在第一个进入“不可推论上下文”之后,只需在函数参数中使用模板参数即可:

template <typename T>
struct type_identity {
    using type = T;
};
template <typename T>
using type_identity_t = typename type_identity<T>::type;

template <class T>
void foo(T, type_identity_t<T>) {}

现在foo(1.0, 1)的含义与foo<double>(1.0, 1)相同,并且函数专业化具有参数(double, double),因此1会从int隐式转换为{{1 }}。相反,double表示foo(1, 1.0),而foo<int>(1, 1.0)被隐式转换为1.0

(请注意std::type_identity_t is coming in C++20。)