Enlarge link option and equality comparison

The following program cancels:

#include <boost/variant.hpp>

using variant_type = boost::variant< int&, std::string& >;

int main () {
    int a, b;

    variant_type v (a), u (b);
    v == u;

    return 0;
}

from:

$ g++ -std=c++14 t.cpp && ./a.out 
a.out: /opt/boost/default/include/boost/variant/detail/forced_return.hpp:39: T boost::detail::variant::forced_return() [with T = const int&]: Assertion `false' failed.
Aborted (core dumped)

AFAICT, you cannot compare for equality between link options other than const, due to incorrect overloading of the operator function call in the known_get class. known_get is created for const T in the companion visitor instead of what seems to be T (variant.hpp: 905 in version 1.59.0).

Did I miss something?

+4
source share
2 answers

I think this is a Boost bug.

type requirements :

  • CopyConstructible or MoveConstructible.
  • The destructor maintains a no-throw safety guarantee.
  • . (. boost::recursive_wrapper<T> , .)

:

  • EqualityComparable: variant EqualityComparable , .

, , . , . , , ,:

template <typename T>
bool operator()(const T& rhs_content) const
{
    // Since the precondition ensures lhs and rhs types are same, get T...
    known_get<const T> getter;
    const T& lhs_content = lhs_.apply_visitor(getter);

    // ...and compare lhs and rhs contents:
    return Comp()(lhs_content, rhs_content);
}

const T . , , known_get , :

T& operator()(T& operand) const BOOST_NOEXCEPT
{
    return operand;
}

template <typename U>
T& operator()(U& ) const
{
    // logical error to be here: see precondition above
    BOOST_ASSERT(false);
    return ::boost::detail::variant::forced_return<T&>();
}

int& :

const int& operator()(const int& ) const;
const int& operator()(int& ) const; [ U = int ]

, , , const-, . , . !

const comparer :

template <typename T>
bool operator()(T& rhs_content) const
{
    known_get<T> getter;
    T& lhs_content = lhs_.apply_visitor(getter);

    return Comp()(lhs_content, rhs_content);
}

, const.

+3

ok, ( ).

boost:: variant ==, .

, .

() , ( clang), .

#include <string>
#include <boost/variant.hpp>

using variant_type = boost::variant< int&, std::string& >;

struct is_equal
{
    // compare int with int
    bool operator()(const int& l, const int& r) const {
        return l == r;
    }

    // compare string with string
    bool operator()(const std::string& l, const std::string& r) const {
        return l == r;
    }

    // anything else compared with anything else compares false.        
    template<class X, class Y>
    bool operator()(const X&, const Y&) const {
        return false;
    }
};

int main () {
    int a = 0, b = 0;

    variant_type v = a, u = b;

    bool ok = boost::apply_visitor(is_equal(), v, u);
//    bool ok = (v == u);

    return 0;
}
0

Source: https://habr.com/ru/post/1612948/


All Articles