Boost logo

Boost :

Subject: Re: [boost] C++11 decltype/SFINAE puzzler
From: Marc Glisse (marc.glisse_at_[hidden])
Date: 2012-07-06 15:54:42


On Fri, 6 Jul 2012, Eric Niebler wrote:

> I'm running into a usability problem with the extended SFINAE rules that
> could effect best practice for all new C++ libraries. I'm hoping some
> clever person in the Boost community can help me.
>
> I find that in highly generic code, using decltype to define the return
> type of functions is very handy. Dave A. suggested a RETURNS macro to
> simplify this idiom:
>
> <https://groups.google.com/d/msg/boost-devel-archive/OzJ5Ft3pSnU/b_Ter9bgNqAJ>
>
> It's used like this:
>
> template<typename T>
> auto foo( T && t ) RETURNS( some-expression-using-t );
>
> This is great and I use it a lot. Now, imagine you have a library of
> such functions calling other such functions: function A calls B calls
> ... calls Y, calls Z, all of which use decltype to declare their return
> types. Now, the user calls A passing a variable t for which the
> expression in Z's return type calculation makes no sense. Extended
> SFINAE kicks in, and Z simply disappears. Since Z has disappeared, the
> expression in Y's return type makes no sense, so Y disappears, too. And
> so on up the chain.
>
> The end result is that the user is presented with an error like: "no
> viable function A, template substitution failed." The user is given no
> information about which function in the chain failed to compile, or why.
> This is a serious usability problem!

... in your compiler.

> All suggestions welcome,

Use g++.

template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();}
template<class T> auto g(T x)->decltype(h(x)){return h(x);}
template<class T> auto f(T x)->decltype(g(x)){return g(x);}
int main(){
   f(3);
}

e.cc: In function 'int main()':
e.cc:5:6: error: no matching function for call to 'f(int)'
    f(3);
       ^
e.cc:5:6: note: candidate is:
e.cc:3:24: note: template<class T> decltype (g(x)) f(T)
  template<class T> auto f(T x)->decltype(g(x)){return g(x);}
                         ^
e.cc:3:24: note: template argument deduction/substitution failed:
e.cc: In substitution of 'template<class T> decltype (g(x)) f(T) [with T =
int]':
e.cc:5:6: required from here
e.cc:3:24: error: no matching function for call to 'g(int&)'
e.cc:3:24: note: candidate is:
e.cc:2:24: note: template<class T> decltype (h(x)) g(T)
  template<class T> auto g(T x)->decltype(h(x)){return h(x);}
                         ^
e.cc:2:24: note: template argument deduction/substitution failed:
e.cc: In substitution of 'template<class T> decltype (h(x)) g(T) [with T =
int]':
e.cc:3:24: required by substitution of 'template<class T> decltype
(g(x)) f(T) [with T = int]'
e.cc:5:6: required from here
e.cc:2:24: error: no matching function for call to 'h(int&)'
e.cc:2:24: note: candidate is:
e.cc:1:24: note: template<class T> decltype (x.smurf()) h(T)
  template<class T> auto h(T x)->decltype(x.smurf()){return x.smurf();}
                         ^
e.cc:1:24: note: template argument deduction/substitution failed:
e.cc: In substitution of 'template<class T> decltype (x.smurf()) h(T)
[with T = int]':
e.cc:2:24: required by substitution of 'template<class T> decltype
(h(x)) g(T) [with T = int]'
e.cc:3:24: required by substitution of 'template<class T> decltype
(g(x)) f(T) [with T = int]'
e.cc:5:6: required from here
e.cc:1:24: error: request for member 'smurf' in 'x', which is of non-class
type 'int'

-- 
Marc Glisse

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