Boost logo

Boost :

Subject: [boost] C++11 decltype/SFINAE puzzler
From: Eric Niebler (eric_at_[hidden])
Date: 2012-07-06 15:41:14


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!

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?

The only solution I can think of is turn all the free functions in the
chain into function objects and then using std::result_of to compute
return types for them instead of using decltype directly. That means
Dave's (very convenient!) RETURNS macro shouldn't be used, which is a
bummer. (I think it also means that we need a noexcept_of template that
computes the noexcept of an expression without causing the expression to
appear in the function declaration, but that depends on how
<http://llvm.org/bugs/show_bug.cgi?id=13286> gets resolved.)

All suggestions welcome,

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

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