Search code examples
c++c++17c++builder

Is C++Builder (10.4 and above) a C++17 compliant compiler


I've been using previous version of C++ Builder and I decided to upgrade to 10.4 before 11.2 as I need C++17 compatibility. I'm already facing an issue with "scoped_lock" (C++ Builder 10.4 community edition => scoped_lock are missing (at least seems to be a path mess)) but now even that example from ccp_reference does not compile

#include <variant>
#include <string>
#include <cassert>
#include <iostream>

int main()
{
    std::variant<int, float> v, w;
    v = 42; // v contains int
    int i = std::get<int>(v);
    assert(42 == i); // succeeds
    w = std::get<int>(v);
    w = std::get<0>(v); // same effect as the previous line
    w = v; // same effect as the previous line

//  std::get<double>(v); // error: no double in [int, float]
//  std::get<3>(v);      // error: valid index values are 0 and 1

    try {
        std::get<float>(w); // w contains int, not float: will throw
    }
    catch (const std::bad_variant_access& ex) {
        std::cout << ex.what() << '\n';
    }

    using namespace std::literals;

    std::variant<std::string> x("abc");
    // converting constructors work when unambiguous
    x = "def"; // converting assignment also works when unambiguous

    std::variant<std::string, void const*> y("abc");
    // casts to void const * when passed a char const *
    assert(std::holds_alternative<void const*>(y)); // succeeds
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // succeeds
}

The compiler whines that there is no viable overload '=' at 2nd line of main (and further on). Basically, variant types do not seem to be usable at all. I've tried to make sure that c++17 is selected and I'm not using the "classic" version, but Clang, but nothing works. So am I missing something big or shall I just give up because that compiler is simply not at C++ 17 level?


Solution

  • std::variant is broken in C++ Builder for some types. However, the compiler is intended to support C++17, and many C++17 features work. You could use boost::variant instead.

    There is a workaround in comments:

    Issue: The assignment and constructor of Dinkumware std::variant checks that the value is assignable to exactly one type (_One_t<is_assignable, _Ty&, _Types&...>). This breaks those operations for a combination from int and double as they are assignable to each other.

    Fix: I've changed _One_ta to _One_ts in file 'variant' lines 607, 611, 614, 918, 919, 920, and 926 and also _One_tc to _One_ts in code lines 624,628, and 631.

    This limits these operators to the same types and works for me. I guess, that unambiguous conversions would be acceptable as well, but I've not checked the standard beyond looking to cppreference.com.