9

Recently, I've started using MSVC to compile a code which was always compiled with GCC and Clang. Some piece of this code produces an interesting compilation error (truncated):

C:/data/msvc/14.33.31424-Pre/include\future(311) error C2678: binary '=': no operator found which takes a left-hand operand of type 'const Result' (or there is no acceptable conversion)
<source>(7): note: could be 'Result &Result::operator =(Result &&)'
<source>(7): note: or       'Result &Result::operator =(const Result &)'

Minimal example of this piece of code:

#include <future>
#include <iostream>

struct Result {
    int data{0};
};

// getting rid of constness resolves the problem for MSVC
using result_t = const Result; 
using promise_result_t = std::promise<result_t>;

auto compute_result(promise_result_t result)
{
    Result some_result{10};
    result.set_value(std::move(some_result));
}

int main()
{
    promise_result_t my_promise;
    auto my_future = my_promise.get_future();
    std::thread thread(compute_result, std::move(my_promise));
    std::cout << "result: " << my_future.get().data;
    thread.join();
    return 0;
}

It is quite clear that removal of const for std::promise storage solves the problem, but I'm curious if anyone has tried to dive deep into the implementations of std::promise for different compilers.

What might be the difference that allows this code to compile and work using GCC and Clang, yet produce a compilation error when using MSVC? (Operating via pointers on stored data in GCC and Clang?)

Stefan Profanter
  • 6,458
  • 6
  • 41
  • 73
  • 1
    I would expect result_t to be non-const anyway since the result will be given a value in the future. (After creating the promise). Though I can't find a description of that limitation https://en.cppreference.com/w/cpp/thread/promise here. So I would be interested in the real answer too – Pepijn Kramer Jul 07 '22 at 08:55
  • 3
    After a quick look at clang it seems like the result is constructed with placement new. However, MSVC uses an assignment for "simple" types, Possibly a failed attempt to optimize storage, as there is also a note *"// TRANSITION, incorrectly assigns _Result when _Ty is default constructible"*. So a known bug, it seems. – BoP Jul 07 '22 at 10:14
  • 1
    at a first glance the standard doesn't mandate any requirements for `R` in `std::future` https://timsong-cpp.github.io/cppwp/n3337/futures.promise so I don't think it's a case of unspecified or undefined behavior. I think one behavior is conformant and the other is bug. I didn't deep dive into it so I could easily be missing something. – bolov Jul 07 '22 at 10:43

1 Answers1

5

Looks like an MSVC issue, reported here:

https://developercommunity.visualstudio.com/t/std::promise-works-incorrectly-for-const/10092031

and linked to the issue on GitHub:

https://github.com/microsoft/STL/issues/2599

Stefan Profanter
  • 6,458
  • 6
  • 41
  • 73
Zag
  • 51
  • 1