Skip to content

Commit

Permalink
Work around an MSVC bug in C++20 mode (facebookexperimental#492)
Browse files Browse the repository at this point in the history
* Work around an MSVC bug in C++20 mode

PR facebookexperimental#489 seems to have found a bug in MSVC when compiling
`variant_sender` in C++20 mode.  This diff adds a test that I expect to
pass everywhere but fail to build with MSVC.  The next diff will fix the
problem with a work-around.

* Actually work around MSVC's bug

This diff works around the bug revealed by the test added in the
previous diff.
  • Loading branch information
ispeters authored and janondrusek committed Mar 27, 2023
1 parent bc7bd90 commit 512efff
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 5 deletions.
12 changes: 9 additions & 3 deletions include/unifex/variant_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,19 @@ class _sender<Senders...>::type {
friend auto tag_invoke(tag_t<connect>, This&& that, Receiver&& r)
noexcept(std::conjunction_v<unifex::is_nothrow_connectable<match_reference_t<This, Senders>, Receiver>...>)
{
// MSVC needs this type alias declared outside the lambda below to reliably compile
// the visit() expression as C++20
using op_t = operation<connect_result_t<Senders, Receiver>...>;
return std::visit(
[&r](auto&& sender) noexcept(
unifex::is_nothrow_connectable_v<decltype(sender), Receiver>) {
return operation<connect_result_t<Senders, Receiver>...>{
static_cast<decltype(sender)&&>(sender), static_cast<Receiver&&>(r)};
// MSVC doesn't like static_cast<Receiver&&>(r) in some cases when compiling
// as C++20, but seems to reliably do the right thing with
// static_cast<decltype(r)>(r)
return op_t{
static_cast<decltype(sender)&&>(sender), static_cast<decltype(r)>(r)};
},
std::move(static_cast<decltype(that)>(that).senderVariant_));
static_cast<decltype(that)>(that).senderVariant_);
}
};
} // namespace _variant_sender
Expand Down
7 changes: 5 additions & 2 deletions test/variant_sender_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@
* limitations under the License.
*/
#include <unifex/any_sender_of.hpp>
#include <unifex/async_manual_reset_event.hpp>
#include <unifex/defer.hpp>
#include <unifex/dematerialize.hpp>
#include <unifex/just.hpp>
#include <unifex/just_error.hpp>
#include <unifex/just_done.hpp>
#include <unifex/just_error.hpp>
#include <unifex/let_value.hpp>
#include <unifex/materialize.hpp>
#include <unifex/variant_sender.hpp>
#include <unifex/scheduler_concepts.hpp>
#include <unifex/sync_wait.hpp>
#include <unifex/then.hpp>
#include <unifex/timed_single_thread_context.hpp>
#include <unifex/variant_sender.hpp>

#include <chrono>
#include <iostream>
Expand Down Expand Up @@ -231,3 +233,4 @@ TEST(Variant, TestNoexcept_RvalueRef) {
auto rvalue_no_except = is_noexcept<false, true, false>::value;
EXPECT_TRUE(rvalue_no_except);
}

0 comments on commit 512efff

Please sign in to comment.