Skip to content

Commit

Permalink
Fix return value type deduction for nonstd::visit #28 (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
flexferrum authored and martinmoene committed Nov 6, 2018
1 parent d33e5cd commit 0efbca4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 3 deletions.
4 changes: 2 additions & 2 deletions include/nonstd/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1924,7 +1924,7 @@ struct VisitorApplicator
template< size_t NumVars, typename Visitor, typename ... V >
struct VisitorImpl
{
typedef decltype(std::declval<Visitor>()(get<0>(std::declval<V>())...)) result_type;
typedef decltype(std::declval<Visitor>()(get<0>(static_cast<const V&>(std::declval<V>()))...)) result_type;
typedef VisitorApplicator<result_type> applicator_type;
};
#endif
Expand Down Expand Up @@ -2125,4 +2125,4 @@ struct hash< nonstd::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T

#endif // variant_USES_STD_VARIANT

#endif // NONSTD_VARIANT_LITE_HPP
#endif // NONSTD_VARIANT_LITE_HPP
2 changes: 1 addition & 1 deletion template/variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1598,7 +1598,7 @@ struct VisitorApplicator
template< size_t NumVars, typename Visitor, typename ... V >
struct VisitorImpl
{
typedef decltype(std::declval<Visitor>()(get<0>(std::declval<V>())...)) result_type;
typedef decltype(std::declval<Visitor>()(get<0>(static_cast<const V&>(std::declval<V>()))...)) result_type;
typedef VisitorApplicator<result_type> applicator_type;
};
#endif
Expand Down
79 changes: 79 additions & 0 deletions test/variant.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include "variant-main.t.hpp"

#include <memory>

namespace {

// ensure comparison of pointers for lest:
Expand Down Expand Up @@ -1007,6 +1009,83 @@ CASE( "variant: Allows to check for content by type" )
#endif
}

#if variant_CPP14_OR_GREATER
struct RVRefTestVisitor
{
std::string operator()(int val) const
{
std::ostringstream os;
os << val;
return os.str();
}
std::string operator()(const std::string& val) const
{
std::ostringstream os;
os << val;
return os.str();
}

template<typename ... Args>
std::string operator()(const variant<Args...>& var) const
{
return visit(RVRefTestVisitor(), var);
}

template<typename U>
std::string operator()(U&&) const
{
static_assert(std::is_const<U>::value, "Wrong branch!");
return ">>> Broken branch! <<<";
}
};

struct Unwrapper
{
RVRefTestVisitor* m_v;

Unwrapper(RVRefTestVisitor* v)
: m_v(v)
{}

template<typename T>
auto& Unwrap(T&& val) const
{
return std::forward<T>(val);
}

template<typename T>
const auto& Unwrap(std::shared_ptr<T> val) const
{
const auto& result = *val.get();
return result;
}

template<typename ... Args>
auto operator()(Args&& ... args) const
{
return (*m_v)(Unwrap(std::forward<Args>(args))...);
}

};

CASE( "variant: Allows to visit contents (args: 1)" )
{
typedef std::shared_ptr<std::string> string_ptr_t;
typedef variant< int, std::string, string_ptr_t > var_t;
string_ptr_t inner = std::make_shared<std::string>("hello1");

var_t vstr1 = inner;
var_t vstr2 = std::string("hello2");
RVRefTestVisitor visitor;

std::string rs1 = visit(Unwrapper(&visitor), vstr1);
std::string rs2 = visit(Unwrapper(&visitor), vstr2);

EXPECT( rs1 == "hello1" );
EXPECT( rs2 == "hello2" );
}
#endif

CASE( "variant: Allows to get element by type" )
{
variant<int, S> var( S( 7 ) );
Expand Down

0 comments on commit 0efbca4

Please sign in to comment.