C++11:无法推断模板参数

C++11: Unable to infer template argument

本文关键字:参数 C++11      更新时间:2023-10-16

>行:

    auto test = add<Suc < Suc < Suc < Suc < Zero > > > > > (three, one);

如果我替换为:

    auto test = add(three, one);

我忽略了错误的候选模板:无法使用 std=c++11 的 Clang 编译器推断模板参数"W" 我无法想象任何其他值满足 W 对于它,有没有办法修复它?

#include <type_traits>
template<typename T>
class Nat {
};
class Zero : public Nat<Zero> {
};
template<typename T, 
    typename std::enable_if<std::is_base_of<Nat<T>, T>::value>::type* = nullptr>
class Suc : public Nat<Suc<T> > {
 public:
  T val;
  explicit Suc(T v): val(v) {}
};
template<typename T>
Suc<T> suc(T val) {
    Suc<T> next(val);
    return next; 
}
template<typename W, typename U, typename V,
    typename std::enable_if<std::is_base_of<Nat<W>, W>::value>::type* = nullptr,
    typename std::enable_if<std::is_base_of<Nat<U>, U>::value>::type* = nullptr,
    typename std::enable_if<std::is_base_of<Nat<V>, V>::value>::type* = nullptr
    >
W add(Suc<U> m, V n) {
    Suc<V> next (n);
    return add<W>(m.val, next);
}
template<typename V>
V add(Zero m, V n) {
    return n;
}
int main() {
    Zero zero;
    auto one = suc(zero);
    auto two = suc(one);
    auto three = suc(two);
    auto four = suc(three);
    auto test = add<Suc < Suc < Suc < Suc < Zero > > > > > (three, one);
    return 0;
}

控制台输出:

c++ -std=c++11 main.cc
main.cc:48:17: error: no matching function
      for call to 'add'
    auto test = add(three, one);
                ^~~
main.cc:35:3: note: candidate function
      template not viable: no known
      conversion from 'Suc<Suc<Suc<Zero,
      nullptr>, nullptr>, nullptr>' to
      'Zero' for 1st argument
V add(Zero m, V n) {
  ^
main.cc:29:3: note: candidate template
      ignored: couldn't infer template
      argument 'W'
W add(Suc<U> m, V n) {
  ^
1 error generated.

此错误消息告诉您原因:

主.cc:29:3:注意:候选模板 已忽略:无法推断模板 参数"W">

返回类型是模板参数,但编译器无法从函数参数推断返回类型,您必须指定它。

但是,decltype可以帮助您计算返回类型应该是什么:

template<typename U, typename V>
auto add(Suc<U> m, V n) -> decltype(add(m.val, Suc<V>(n))) {
    Suc<V> next (n);
    return add(m.val, next);
}