the line:
auto test = add<Suc < Suc < Suc < Suc < Zero > > > > > (three, one);
if I replace with:
auto test = add(three, one);
I get error candidate template ignored: couldn't infer template argument 'W', using a Clang compiler with std=c++11 I can't imagine any other value satisfying W for it, is there a way to fix it?
#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;
}
Console output:
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.
This error message is telling you why:
main.cc:29:3: note: candidate template ignored: couldn't infer template argument 'W'
The return type is a template argument, but the compiler can't deduce a return type from the function arguments, you have to specify it.
But, decltype
can help you compute what that return type should be:
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);
}