【问题标题】:C++11: Unable to infer template argumentC++11:无法推断模板参数
【发布时间】:2019-11-20 17:10:36
【问题描述】:

行:

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

如果我替换为:

    auto test = add(three, one);

我得到错误候选模板被忽略:无法推断模板参数“W”,使用带有 std=c++11 的 Clang 编译器 我无法想象任何其他满足 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.

【问题讨论】:

    标签: c++ c++11 templates algebraic-data-types


    【解决方案1】:

    此错误消息告诉您原因:

    main.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);
    }
    

    【讨论】:

    • 我当然明白。但是如果您尝试 W 的任何其他值,它将无法编译 - 因为没有匹配的专业化。有没有办法可以提示编译器这是唯一有效的返回类型?
    • 如果我不完全理解,我很抱歉。只能有一种返回类型,即您在函数签名中使用的那种。从函数体中返回任何其他内容,编译器会报错。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2013-02-18
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多