$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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.