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

Time:01-27

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:

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?

CodePudding user response:

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.

  •  Tags:  
  • Related