Boost logo

Boost :

Subject: Re: [boost] C++11 decltype/SFINAE puzzler
From: Andrew Sutton (asutton.list_at_[hidden])
Date: 2012-07-06 16:15:41


> So, my question is: what can be done about this? Can we get the benefit
> of automatic type deduction in return types without causing SFINAE to
> drop functions from the overload set? Is there another trick we can use
> to report errors meaningfully when APIs are misused?

No!

Just kidding. I was actually wondering something very similar earlier
today. How can we intelligently document the causes of SFINAE-based
overloading errors? I don't have a good answer yet.

But I plugged in the problem you mentioned and checked it out with GCC
4.8 (compiled from trunk a month ago -- has it been so long?).

template <typename T>
  auto h(T x) -> decltype(*x) { return *x; }

template <typename T>
  auto g(T x) -> decltype(h(x)) { return h(x); }

template <typename T>
  auto f(T x) -> decltype(g(x)) { return g(x); };

int main()
{
  f(0);
}

And get this as output:

foo.cpp: In function ‘int main()’:
foo.cpp:22:6: error: no matching function for call to ‘f(int)’
   f(0);
      ^
foo.cpp:22:6: note: candidate is:
foo.cpp:18:8: note: template<class T> decltype (g(x)) f(T)
   auto f(T x) -> decltype(g(x)) { return g(x); };
        ^
foo.cpp:18:8: note: template argument deduction/substitution failed:
foo.cpp: In substitution of ‘template<class T> decltype (g(x)) f(T)
[with T = int]’:
foo.cpp:22:6: required from here
foo.cpp:18:8: error: no matching function for call to ‘g(int&)’
foo.cpp:18:8: note: candidate is:
foo.cpp:15:8: note: template<class T> decltype (h(x)) g(T)
   auto g(T x) -> decltype(h(x)) { return h(x); }
        ^
foo.cpp:15:8: note: template argument deduction/substitution failed:
foo.cpp: In substitution of ‘template<class T> decltype (h(x)) g(T)
[with T = int]’:
foo.cpp:18:8: required by substitution of ‘template<class T>
decltype (g(x)) f(T) [with T = int]’
foo.cpp:22:6: required from here
foo.cpp:15:8: error: no matching function for call to ‘h(int&)’
foo.cpp:15:8: note: candidate is:
foo.cpp:12:8: note: template<class T> decltype (* x) h(T)
   auto h(T x) -> decltype(*x) { return *x; }
        ^
foo.cpp:12:8: note: template argument deduction/substitution failed:
foo.cpp: In substitution of ‘template<class T> decltype (* x) h(T)
[with T = int]’:
foo.cpp:15:8: required by substitution of ‘template<class T>
decltype (h(x)) g(T) [with T = int]’
foo.cpp:18:8: required by substitution of ‘template<class T>
decltype (g(x)) f(T) [with T = int]’
foo.cpp:22:6: required from here
foo.cpp:12:27: error: invalid type argument of unary ‘*’ (have ‘int’)
   auto h(T x) -> decltype(*x) { return *x; }

So GCC at least is documenting the root cause of the error. It would
still be nice to customize error reporting for certain classes of
failures in an API.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk