Skip to content

Instantly share code, notes, and snippets.

@pfultz2
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pfultz2/3d66795ef18361699fbb to your computer and use it in GitHub Desktop.
Save pfultz2/3d66795ef18361699fbb to your computer and use it in GitHub Desktop.
Transporting substitution failures
#include <iostream>
#include <vector>
#include <list>
template<class T>
struct always_void
{
typedef void type;
};
struct identity
{
template<class T>
constexpr T operator()(T&& x) const
{
return std::forward<T>(x);
}
};
template<class F, class=void>
struct get_failure
{
template<class... Ts>
struct of
{
template<class Id>
using apply = decltype(Id()(std::declval<F>())(std::declval<Ts>()...));
};
};
template<class F>
struct get_failure<F, typename always_void<
typename F::failure
>::type>
: F::failure
{};
// Workaround for some compilers
template<class Failure, class... Ts>
struct apply_failure
: Failure::template of<Ts...>
{};
// A template alias to enable the function
template<class Id, class Failure, class... Ts>
using enabled = typename apply_failure<Failure, Ts...>::template apply<Id>;
template<class F, class Failure=get_failure<F>>
struct reveal_failure
{
// identity is passed in as a default template parameter so the
// subtitution failure is delayed until the function is called
template<class... Ts, class Id=identity, class=enabled<Id, Failure, Ts...>>
auto operator()(Ts&&... xs) const -> decltype(F()(std::forward<Ts>(xs)...))
{
return F()(std::forward<Ts>(xs)...);
}
};
struct h_f
{
struct failure
{
template<class... Ts>
struct of;
template<class T>
struct of<T>
{
template<class Id>
using apply = decltype(*(Id()(std::declval<T>())));
};
};
template<class T>
auto operator()(T x) const -> decltype(*x) { return *x; }
};
constexpr static h_f h = {};
struct g_f
{
struct failure
: get_failure<h_f>
{};
template<class T>
auto operator()(T x) const -> decltype(h(x)) { return h(x); }
};
constexpr static g_f g = {};
struct f_f
{
struct failure
: get_failure<g_f>
{};
template<class T>
auto operator()(T x) const -> decltype(g(x)) { return g(x); };
};
constexpr static reveal_failure<f_f> f = {};
int main()
{
f(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment