Skip to content

Commit

Permalink
Merge 1c4d882 into 4a448b2
Browse files Browse the repository at this point in the history
  • Loading branch information
ldionne committed Nov 15, 2018
2 parents 4a448b2 + 1c4d882 commit 3493618
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 24 deletions.
36 changes: 12 additions & 24 deletions include/boost/variant/detail/apply_visitor_unary.hpp
Expand Up @@ -121,39 +121,27 @@ struct result_multideduce1 {
begin_it, boost::mpl::int_<boost::mpl::size<types>::type::value - 1>
>::type last_it;

// For metaprogramming purposes ONLY! Do not use this method (and class) at runtime!
static Visitor& vis() BOOST_NOEXCEPT {
// Functions that work with lambdas must be defined in same translation unit.
// Because of that, we can not use `boost::decval<Visitor&>()` here.
Visitor&(*f)() = 0; // pointer to function
return f();
}

static decltype(auto) deduce_impl(last_it, unsigned /*helper*/) {
typedef typename boost::mpl::deref<last_it>::type value_t;
return vis()( boost::declval< value_t& >() );
}

template <class It>
static decltype(auto) deduce_impl(It, unsigned helper) {
template <class It, class Dummy = void> // avoid explicit specialization in class scope
struct deduce_impl {
typedef typename boost::mpl::next<It>::type next_t;
typedef typename boost::mpl::deref<It>::type value_t;
if (helper == boost::mpl::distance<begin_it, It>::type::value) {
return deduce_impl(next_t(), ++helper);
}
typedef decltype(true ? boost::declval< Visitor& >()( boost::declval< value_t& >() )
: boost::declval< typename deduce_impl<next_t>::type >()) type;
};

return vis()( boost::declval< value_t& >() );
}
template <class Dummy>
struct deduce_impl<last_it, Dummy> {
typedef typename boost::mpl::deref<last_it>::type value_t;
typedef decltype(boost::declval< Visitor& >()( boost::declval< value_t& >() )) type;
};

static decltype(auto) deduce() {
return deduce_impl(begin_it(), 0);
}
typedef typename deduce_impl<begin_it>::type type;
};

template <class Visitor, class Variant>
struct result_wrapper1
{
typedef decltype(result_multideduce1<Visitor, Variant>::deduce()) result_type;
typedef typename result_multideduce1<Visitor, Variant>::type result_type;

Visitor&& visitor_;
explicit result_wrapper1(Visitor&& visitor) BOOST_NOEXCEPT
Expand Down
5 changes: 5 additions & 0 deletions test/Jamfile.v2
Expand Up @@ -28,6 +28,11 @@ test-suite variant
[ run recursive_variant_test.cpp ]
[ run variant_reference_test.cpp ]
[ run variant_comparison_test.cpp ]
[ run variant_visit_internal_linkage.cpp : : :
<toolset>darwin:<cxxflags>-std=c++14
: variant_visit_internal_linkage_test
]

[ run variant_visit_test.cpp ]
[ run variant_get_test.cpp ]
[ compile-fail variant_rvalue_get_with_ampersand_test.cpp ]
Expand Down
33 changes: 33 additions & 0 deletions test/variant_visit_internal_linkage.cpp
@@ -0,0 +1,33 @@
//-----------------------------------------------------------------------------
// boost-libs variant/test/variant_visit_internal_linkage.cpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// This test checks that we can visit a variant containing a type that has
// internal linkage (anonymous namespace).

#include "boost/test/minimal.hpp"
#include "boost/variant/variant.hpp"


namespace {
struct Foo { };

struct Visitor {
void operator()(Foo const&) const { }
};
}

void run() {
boost::variant<Foo> v = Foo();
boost::apply_visitor(Visitor(), v);
}

int test_main(int, char**) {
run();
return 0;
}

0 comments on commit 3493618

Please sign in to comment.