Code Monkey home page Code Monkey logo

variant2's Introduction

Boost.Variant2

This repository contains a never-valueless, strong guarantee, C++11/14/17 implementation of std::variant. See the documentation for more information.

The library is part of Boost, starting from release 1.71. It depends on Boost.Mp11, Boost.Config, and Boost.Assert.

Supported compilers:

  • g++ 4.8 or later with -std=c++11 or above
  • clang++ 3.9 or later with -std=c++11 or above
  • Visual Studio 2015 or later

Tested on Github Actions and Appveyor.

variant2's People

Contributors

13steinj avatar akrzemi1 avatar eldiener avatar k-ballo avatar lastique avatar pdimov avatar vinniefalco avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

variant2's Issues

support references as bounded types?

variant2 cannot have references as bounded types, https://godbolt.org/z/mnP-CU, which is conforming with std::variant, but this could be another improvement over std::variant if it is not too much work to implement. boost::variant is supporting them and I am using this in boost.histogram in this function
https://github.com/HDembinski/histogram/blob/5ae08d40c26f8db0613545b84a4c0b60c3729102/include/boost/histogram/detail/axes.hpp#L47
which allows me to get a reference to an element of a std::tuple with a run-time index.

Related SO question:
https://stackoverflow.com/questions/54218595/why-are-references-forbidden-in-stdvariant

Add stream insertion operator?

boost::variant has a stream insertion operator (https://www.boost.org/doc/libs/1_77_0/doc/html/variant/reference.html#header.boost.variant.variant_hpp). I don't know why it was not included in std::variant, but people are having problems with that (https://cpplang.slack.com/messages/C21PKDHSL/p1586635254026300).

I'm not sure if defining it myself in boost::variant2 is as bad as defining it in std, but unless there is a reason not to adding a stream insertion operator to boost::variant2 could make people lives easier.

Many tests failed in compilation for "comparison of integers of different signs" in Windows

Hi,
I found that many tests failed in compilation for "comparison of integers of different signs" in windows. Take variant_copy_assign.cpp as an example. When executing below command,
clang-cl -m32 variant_copy_assign.cpp -o variant_copy_assign.o /TP /Z7 /Od /Ob0 /W4 /WX /GR /MDd /EHs /std:c++17 -D_CRT_USE_BUILTIN_OFFSETOF -c -DBOOST_ALL_NO_LIB=1 -I"..\..\.."
it will get following error message, which is caused by the return value type size_t of function index().

In file included from variant_copy_assign.cpp:10:
......\boost/core/lightweight_test.hpp(142,62): error: comparison of integers of different signs: 'const unsigned int' and 'const int' [-Werror,-Wsign-compare]
bool operator()(const T& t, const U& u) const { return t == u; }
~ ^ ~
......\boost/core/lightweight_test.hpp(181,9): note: in instantiation of function template specialization 'boost::detail::lw_test_eq::operator()<unsigned int, int>' requested here
if( pred(t, u) )
^
variant_copy_assign.cpp(84,9): note: in instantiation of function template specialization 'boost::detail::test_with_impl<boost::detail::lw_test_eq, unsigned int, int>' requested here
BOOST_TEST_EQ( v.index(), 0 );
^
......\boost/core/lightweight_test.hpp(405,55): note: expanded from macro 'BOOST_TEST_EQ'
#define BOOST_TEST_EQ(expr1,expr2) ( ::boost::detail::test_with_impl(::boost::detail::lw_test_eq(), #expr1, #expr2, FILE, LINE, BOOST_CURRENT_FUNCTION, expr1, expr2) )
^
1 error generated.

This test failed in 64-bit mode too. For 32-bit mode clang-cl, size_t means unsigned int, while for 64-bit mode clang-cl, it means unsigned long long. These two types are both different with expected type int, so the test got failed.
Can we make some changes to avoid this issue? Maybe change size_t to int for the return value type of index()?

README.md and documentation should better explain relation to boost::variant

Visitors who are not well-versed in the history of boost::variant and std::variant don't understand the rationale for having a "variant2" library:

  • Was it created before or after variants became part of the standard?
  • Is it a replacement for boost variant? for std::variant?
  • If so, what, in a nutshell, is the problem with those?
  • If not, why, in a nutshell, create yet another variant class?

The README.md should answer this at least briefly; and the documentation - more thoroughly. Currently that's not the case.

-Wextra warning triggered in gcc-5

I am seeing a new warning in gcc-5 in boost.histogram, which uses boost.variant2:

../../boost/variant2/variant.hpp:1116:5: warning: base class ‘struct boost::variant2::detail::variant_base_impl<false, true, T1, T2, T3 >’ should be explicitly initialized in the copy constructor [-Wextra]
     variant_cc_base_impl( variant_cc_base_impl const& r )
     ^

The warning can be "fixed" by adding

        : variant_base()

in line 1118. Similar changes would then be required in line 1272.

Hashing support

variant2 doesn't seem to support hashing (either std::hash or boost::hash). It would be nice if it had support for either or both.

For reference, std::variant supports the former and boost::variant supports both.

Note that AFAICS behaviors of std::hash and boost::hash aren't exactly same. std::hash will be disabled if any T is non-hashable, but boost::hash causes error while visiting for the same case (as of Boost 1.71).

Thanks for this great library.

Inheriting constructors issue with older compilers

With clang < 4 and gcc < 7 and probably latest MSVC, the following code and godbolt fail to compile:

#include <boost/variant2/variant.hpp>

template <typename ...T>
class any_type : boost::variant2::variant<T...>
{
    using parent_t = boost::variant2::variant<T...>;

    using parent_t::parent_t;
};

struct foo
{
    foo() {}
    foo(int i_arg) : i(i_arg) {}
    foo(foo const& rhs) {}

    template <typename T>
    foo(T const& rhs) {
        rhs.bar();
    }

    int i{0};
};

int main(int argc, char *argv[])
{
    using any_t = any_type<int, double, foo>;

    any_t a(1);
    any_t b(a);
}

The issue comes from foo's converting constructor.

Related to boostorg/gil#526

Visiting class derived from variant

Given

template <typename ...Types>
struct my_variant : boost::variant2::variant<Types...> { };

I looks like it is not possible to visit my_variant:

boost::variant2::variant<int, double> v1;
my_variant<int, double> v2;

auto visitor = [](auto&& v) { std::cout << v << std::endl; };

variant::visit(visitor, v1); //OK
variant::visit(visitor, v2); //KO error: 'value' is not a member of 'boost::variant2::variant_size<my_variant<...>>

This kind of construct is used in Boost.GIL for example and we would like to deprecate gil::apply_operations in the future.

holds_alternative<T>, get<T> overconstrained

There's no good reason for these to not compile when T occurs more than once in the list of alternatives, as it's possible to make them work as expected. In the unlikely case the static_assert is desired, the user can easily write it himself.

Support variant<void>, variant<T&>

This as a side effect will make it possible to remove the result<void> specialization, and will obviate the need for a result<T&> specialization.

void will need to be replaced in variant_base with variant2::void_, and T& - with either std::reference_wrapper<T> or variant2::detail::refwrap<T>.

variant::operator== not considered constexpr in MSVC under certain circumstances

Hi,

I have been hitting a problem on MSVC when using variant::operator== in a constexpr context. Here is an example on Compiler Explorer of the behavior I'm seeing: https://godbolt.org/z/h4z9b8. Here is the code for reference:

#include <boost/variant2/variant.hpp>

using boost::variant2::monostate;

using myvariant = boost::variant2::variant<
    monostate,
    int
>;

int main()
{
    constexpr myvariant v0 {monostate{}};
    constexpr myvariant v1 {monostate{}};
    static_assert(v0 == v0, ""); // rejects this as not constexpr
}

Works fine on clang and gcc. Interestingly, if I replace the monostate by a type like float or string_view, MSVC compiles it correctly.

Use case: I am using variant2 in Boost.Mysql to represent database values, and hit this when testing operator== for my value class.

Thanks.

The introduction of `operator<<` breaks existing code

The introduction of operator<< in e668c09 breaks existing code.

For example

#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include <boost/variant2/variant.hpp>

struct my_type{};

bool
operator==(const my_type&, const my_type&) {
	return true;
}

TEST_CASE( "Test" ) {
    REQUIRE( boost::variant2::variant<int,my_type>{} == boost::variant2::variant<int,my_type>{} );
}

works with Boost 1.77 but not with Boost 1.78.

I have not looked at the details. But Catch uses operator<< if available (https://github.com/catchorg/Catch2/blob/v2.x/docs/tostring.md / https://github.com/catchorg/Catch2/blob/v2.x/single_include/catch2/catch.hpp#L1562), and fallback to something else otherwise. It seems Catch now sees variant2 has operator<<, so it doesn't use the fallback, but when it tries to use it it can't unless all the types in the variant have operator<<.

A similar thing happens at the very least with https://github.com/rollbear/trompeloeil.

Spurious -Wuninitialized for monostate emplace at -Og or with asan since gcc 12.1

Upstream: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111944

#include <boost/variant2/variant.hpp>
int main() {
    boost::variant2::variant<boost::variant2::monostate, int> r;
    r.emplace<boost::variant2::monostate>();
}

gcc 12.1+, -Og or -O -fsanitize=address, -Wuninitialized:

In member function 'constexpr void boost::variant2::detail::variant_storage_impl<std::integral_constant<bool, true>, T1, T ...>::emplace_impl(boost::mp11::mp_true, boost::mp11::mp_size_t<I>, A&& ...) [with long unsigned int I = 1; A = {}; T1 = boost::variant2::detail::none; T = {boost::variant2::monostate, int}]',
    inlined from 'constexpr void boost::variant2::detail::variant_storage_impl<std::integral_constant<bool, true>, T1, T ...>::emplace(boost::mp11::mp_size_t<I>, A&& ...) [with long unsigned int I = 1; A = {}; T1 = boost::variant2::detail::none; T = {boost::variant2::monostate, int}]' at boost/variant2/variant.hpp:705:27,
    inlined from 'constexpr void boost::variant2::detail::variant_base_impl<true, true, T ...>::emplace_impl(boost::mp11::mp_true, A&& ...) [with long unsigned int J = 1; U = boost::variant2::monostate; A = {}; T = {boost::variant2::monostate, int}]' at boost/variant2/variant.hpp:902:20,
    inlined from 'constexpr void boost::variant2::detail::variant_base_impl<true, true, T ...>::emplace(A&& ...) [with long unsigned int I = 0; A = {}; T = {boost::variant2::monostate, int}]' at boost/variant2/variant.hpp:921:33,
    inlined from 'constexpr U& boost::variant2::variant<T>::emplace(A&& ...) [with U = boost::variant2::monostate; A = {}; E = void; T = {boost::variant2::monostate, int}]' at boost/variant2/variant.hpp:1690:49:
boost/variant2/variant.hpp:696:9: warning: '<anonymous>' is used uninitialized [-Wuninitialized]
  696 |         *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
      |         ^
boost/variant2/variant.hpp: In member function 'constexpr U& boost::variant2::variant<T>::emplace(A&& ...) [with U = boost::variant2::monostate; A = {}; E = void; T = {boost::variant2::monostate, int}]':
boost/variant2/variant.hpp:696:17: note: '<anonymous>' declared here
  696 |         *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This affects Boost.System result<void> (e.g. test/result_emplace.cpp).

You already have a suppression for -Wmaybe-uninitialized, do you want to add one for -Wuninitialized as well?

Consider implementing the <=> for cases unsupported by std::variant

First of all IDK if there are any spaceship plans for variant2 so this is highly speculative.

Secondly I am not some PL expert, and I do not know all C++ corner cases that might make this impossible, this is purely based on what I consider nicer to use.

In the following example to get std::variant <=> to work we must provide<=>for std::is_empty_v<T> == true kind of struct although it has no state.

#include<type_traits>
#include<variant>

struct Empty{
 // variant <=> does not compile without this line       
 auto operator<=>(const Empty& other) const = default;
};

static_assert(std::is_empty_v<Empty>);

int main() {
    std::variant<Empty,int,float> v1,v2;
    v1<=>v2;
}

If <=> support is added to the variant2 it would be nice if he would be able to skip over empty structs when checking that all elements have implemented <=> (he would treat all instances of empty structs as being std::strong_order::equal).

Convenience motivation for this is that unlike some other languages C++ enums can not carry state( IIRC Rust, Swift... can) so people sometimes use variant of structs as a C++ enum. Now some of those structs are pure "tag" or enum struct without any state, it is a bit of a shame to be required add a <=> to them just so they can be put in variant2.

Use `::std::name` instead of `std::name`

The implementation of variant as well as mp11 uses construct std::name to refer to entities from the Standard Library. This makes the following code fail to compile:

// included from <scheduled_times_tibrary.hpp>
namespace scheduled_times_tibrary { 
  namespace std { // Scheduled Time of Departure     
  }
}

// my program:
using namespace ScheduledTimesLibrary;

#include <boost/variant/variant.hpp>

int main() {}

Even if this situation is unlikely, it is easily avoided by referring to the std in the global namespace with ::std::name.

indicator for double storage

It would be nice to enable something like this:

using myvariant = boost::variant2<int, myclass>;
static_assert(myvariant::double_storage_required() == false, "some member is forcing double storage");

add support for no-exceptions

variant2 is using raw throw instead of boost::throw_exception, so it doesn't work with the -fno-exceptions compiler flag. It would be nice to support this, for example, Boost.Histogram needs this functionality to use variant2.

Modular Boost C++ Libraries Request

We are in the process of making B2 build changes to all of the B2 build files
to support "modular" consumption of the Boost Libraries by users. See this list
post for some details: https://lists.boost.org/Archives/boost/2024/01/255704.php

The process requires making a variety of changes to make each Boost library
independent of the super-project structure. But the changes do not remove the
super-project structure or the comprehensive Boost release. The changes make
solely make it possible, optionally, for users, like package manages, to easily
consume libraries individually.

Generally the changes include:

  • Adding a libroot/build.jam.
  • Porting any functionality from libroot/jamfile to libroot/build.jam.
  • Moving boost-install declaration from libroot/build/jamfile is applicable.
  • Adjusting other B2 build files in the library, like test/jamfile, as needed.
  • Possible changes to C++ source files to remove includes relative to the
    super-project boostroot location.

Some examples of such changes:

We are asking how you would like us to handle the changes. We would prefer if
you allow the owners of the Boost.org GitHub project to make changes to B2
build files, as needed, to accomplish the changes. But understand
that you may want to manage the proposed changes yourself.

We previously sent emails to all known maintainers to fill out a form with their
preference. We are contacting you in this issue as we have not gotten a response
to that email. You can see the ongoing responses for that form and the responses
to these issues here https://github.com/users/grafikrobot/projects/1/views/6

We are now asking if you can reply directly to this issue to indicate your
preference of handling the changes. Please supply a response to this question
and close the issue (so that we can verify you are a maintainer).

How would you like the build changes to be processed?

  1. Pull request, reviewed and merged by a BOOSTORG OWNER.
  2. Pull request, reviewed and merged by YOU.
  3. Other. (please specify details in the reply)

Also please indicate any special instructions you want us to consider. Or other
information you want us to be aware of.

Thanks you, René

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.