reveal¶
Header¶
#include <boost/hof/reveal.hpp>
Description¶
The reveal
function adaptor helps shows the error messages that get
masked on some compilers. Sometimes an error in a function that causes a
substitution failure, will remove the function from valid overloads. On
compilers without a backtrace for substitution failure, this will mask the
error inside the function. The reveal
adaptor will expose these error
messages while still keeping the function SFINAE-friendly.
Sample¶
If we take the print
example from the quick start guide like this:
namespace adl {
using std::begin;
template<class R>
auto adl_begin(R&& r) BOOST_HOF_RETURNS(begin(r));
}
BOOST_HOF_STATIC_LAMBDA_FUNCTION(for_each_tuple) = [](const auto& sequence, auto f) BOOST_HOF_RETURNS
(
boost::hof::unpack(boost::hof::proj(f))(sequence)
);
auto print = boost::hof::fix(boost::hof::first_of(
[](auto, const auto& x) -> decltype(std::cout << x, void())
{
std::cout << x << std::endl;
},
[](auto self, const auto& range) -> decltype(self(*adl::adl_begin(range)), void())
{
for(const auto& x:range) self(x);
},
[](auto self, const auto& tuple) -> decltype(for_each_tuple(tuple, self), void())
{
return for_each_tuple(tuple, self);
}
));
Which prints numbers and vectors:
print(5);
std::vector<int> v = { 1, 2, 3, 4 };
print(v);
However, if we pass a type that can’t be printed, we get an error like this:
print.cpp:49:5: error: no matching function for call to object of type 'boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)> >'
print(foo{});
^~~~~
fix.hpp:158:5: note: candidate template ignored: substitution failure [with Ts = <foo>]: no matching function for call to object of type 'const boost::hof::first_of_adaptor<(lambda at
print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)>'
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
Which is short and gives very little information why it can’t be called.
It doesn’t even show the overloads that were try. However, using the
reveal
adaptor we can get more info about the error like this:
print.cpp:49:5: error: no matching function for call to object of type 'boost::hof::reveal_adaptor<boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9),
(lambda at print.cpp:37:9)> >, boost::hof::fix_adaptor<boost::hof::first_of_adaptor<(lambda at print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)> > >'
boost::hof::reveal(print)(foo{});
^~~~~~~~~~~~~~~~~~
reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:29:9)'
constexpr auto operator()(Ts&&... xs) const
^
reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:33:9)'
constexpr auto operator()(Ts&&... xs) const
^
reveal.hpp:149:20: note: candidate template ignored: substitution failure [with Ts = <foo>, $1 = void]: no matching function for call to object of type '(lambda at print.cpp:37:9)'
constexpr auto operator()(Ts&&... xs) const
^
fix.hpp:158:5: note: candidate template ignored: substitution failure [with Ts = <foo>]: no matching function for call to object of type 'const boost::hof::first_of_adaptor<(lambda at
print.cpp:29:9), (lambda at print.cpp:33:9), (lambda at print.cpp:37:9)>'
operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
So now the error has a note for each of the lambda overloads it tried. Of course this can be improved even further by providing custom reporting of failures.
Synopsis¶
template<class F>
reveal_adaptor<F> reveal(F f);
Reporting Failures¶
By default, reveal
reports the substitution failure by trying to call
the function. However, more detail expressions can be be reported from a
template alias by using as_failure
. This is done by defining a nested
failure
struct in the function object and then inheriting from
as_failure
. Also multiple failures can be reported by using
with_failures
.
Synopsis¶
// Report failure by instantiating the Template
template<template<class...> class Template>
struct as_failure;
// Report multiple falures
template<class... Failures>
struct with_failures;
// Report the failure for each function
template<class... Fs>
struct failure_for;
// Get the failure of a function
template<class F>
struct get_failure;
Example¶
#include <boost/hof.hpp>
#include <cassert>
struct sum_f
{
template<class T, class U>
using sum_failure = decltype(std::declval<T>()+std::declval<U>());
struct failure
: boost::hof::as_failure<sum_failure>
{};
template<class T, class U>
auto operator()(T x, U y) const BOOST_HOF_RETURNS(x+y);
};
int main() {
assert(sum_f()(1, 2) == 3);
}