c++ - Using SFINAE to select function based on whether a particular overload of a function exists -
this question has answer here:
i have been trying choose between 2 templated functions based on whether overload operator<<(std::ostream&, const t&)
exists.
example:
template <typename t, typename std::enable_if</* ? */, int>::type = 0> std::string stringify(const t& t) { std::stringstream ss; ss << t; return ss.str(); } template <typename t, typename std::enable_if</* ? */, int>::type = 0> std::string stringify(const t& t) { return "no overload of operator<<"; } struct foo { }; int main() { std::cout << stringify(11) << std::endl; std::cout << stringify(foo{}) << std::endl; }
is possible? , if so, how solve problem?
there's no need enable_if
, use expression sfinae select correct overload when operator<<
present.
namespace detail { template<typename t> auto stringify(std::stringstream& ss, t const& t, bool) -> decltype(ss << t, void(), std::string{}) { ss << t; return ss.str(); } template<typename t> auto stringify(std::stringstream&, t const&, int) -> std::string { return "no overload of operator<<"; } } template <typename t> std::string stringify(const t& t) { std::stringstream ss; return detail::stringify(ss, t, true); }
the stringify
function template delegates 1 of detail::stringify
function templates. then, first 1 selected if expression ss << t
well-formed. unnamed bool
parameter being used disambiguation between 2 detail::stringify
implementations. since primary stringify
function passes true
argument detail::stringify
, first 1 better match when operator<<
overload present. otherwise second 1 selected.
this expression decltype(ss << t, void(), std::string{})
in trailing return type of first stringify
template merits more detailed explanation. here have single expression consisting of 3 sub-expressions separated comma operator.
the first one, ss << t
determines whether function template passes template parameter substitution , added overload resolution set. occur if expression well-formed, i.e. if type in question overloads operator<<
.
the middle sub-expression, void()
doesn't other ensure user-defined operator,
not selected (because cannot overload operator,
void
parameter type).
the third, , rightmost, sub-expression, std::string{}
determines return type of detail::stringify
function.
Comments
Post a Comment