Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

std::barrier is_nothrow_invocable_v<CompletionFunction&> shall be true error

I am trying to simulate a dice roll program, to be more specific get the number of rolls necessary to get n dices to be 6 at the same time.

So this is a textbook example of fork-join model in order to simulate rolls simultaneously and then check result after each iteration.

#include <iostream>
#include <vector>
#include <thread>
#include <random>
#include <array>
#include <barrier>

auto random_int(int min, int max)
{
    static thread_local auto engine = std::default_random_engine{ std::random_device{}() };
    auto dist = std::uniform_int_distribution<>(min, max);
    return dist(engine);
}

int main()
{
    constexpr auto n = 5;
    auto done = false;
    auto dice = std::array<int, n>{};
    auto threads = std::vector<std::thread>{};
    auto n_turns = 0;

    auto check_result = [&]
    {
        ++n_turns;
        auto is_six = [](int i) {return 6 == i; };
        done = std::all_of(std::begin(dice), std::end(dice), is_six);
    };

    auto bar = std::barrier{ n,check_result };

    for (int i = 0; i < n; ++i)
    {
        threads.emplace_back([&, i]{
                while (!done)
                {
                    dice[i] = random_int(1, 6);
                    bar.arrive_and_wait();
                }});
    }

    for (auto&& t : threads)
    {
        t.join();
    }

    std::cout << n_turns << std::endl;
}

And I am getting the following error:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

error C2338: N4861 [thread.barrier.class]/5:
is_nothrow_invocable_v<CompletionFunction&> shall be true
1>C:\Users\eduar\source\repos\C++20\C++20\main.cpp(114): message : see
reference to class template instantiation
‘std::barriermain::<lambda_1>’ being compiled

Can someone please hint what am I doing wrong and how to fix this?

>Solution :

The issue is in the error message. Which is great, even cites exactly the part of the standard which has this requirement: [thread.barrier.class]/5:

CompletionFunction shall meet the Cpp17MoveConstructible (Table 28) and Cpp17Destructible (Table 32) requirements.
is_­nothrow_­invocable_­v<CompletionFunction&> shall be true.

You’re currently missing the last part: your lambda isn’t nothrow-invocable. That’s an easy fix tho:

auto check_result = [&]() noexcept
//                        ^~~~~~~~
{
    ++n_turns;
    auto is_six = [](int i) {return i == 6; };
    done = std::all_of(std::begin(dice), std::end(dice), is_six);
};

I also took the opportunity to flip your Yoda conditional, because there is no reason to write Yoda conditionals.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading