Повышение: сравнение вариантов с apply_visitor

Может кто-нибудь сказать мне, почему я получаю ошибку компилятора для последней строки следующего кода?

примечание: если я удалю следующую строку, мой код будет скомпилирован без ошибок:

appliedEqualityVisitor(compareValue);

Вот код:

#include "boost/variant/variant.hpp"
#include "boost/variant/apply_visitor.hpp"

using namespace std;
using namespace boost;


template<typename T>
struct CheckOneTypeEquality : public boost::static_visitor<>
{
    T const* value;
    bool operator()( T const& other ) const
    {
        return other == *value;
    }
    template<typename U>
    bool operator()( U const& other ) const
    {
        return false;
    }
    CheckOneTypeEquality( T const& value_ ):value(&value_) {}
};

typedef variant<int, string> MyVariant;
typedef apply_visitor_delayed_t<CheckOneTypeEquality<MyVariant>> AppliedEqualityVisitorType;

int main(int argc, char **argv) 
{
    int testValue = 12;
    CheckOneTypeEquality<MyVariant> equalityVisitor(testValue);

    AppliedEqualityVisitorType appliedEqualityVisitor = apply_visitor(equalityVisitor);

    MyVariant compareValue = 13;
    appliedEqualityVisitor(compareValue); // <<<<< compile error here

    return 0;
}

2 ответа

Решение

Проблема связана с вашим классом посетителей. Boost ожидает void operator()(...)вместо этого вы предоставляете operator() это что-то возвращает.

Чтобы ваш шаблон работал, вам нужно изменить посетителя, например:

template<typename T>
struct CheckOneTypeEquality : public boost::static_visitor<>
{
    T const* value;
    mutable bool check;
    void operator()( T const& other ) const
    {
        check = other == *value;
    }
    template<typename U>
    void operator()( U const& other ) const
    {
      check = false;
    }
    CheckOneTypeEquality( T const& value_ ):value(&value_), check(false) {}
};

Затем проверьте результат. Btw. Я не уверен, что ваш конструктор, которому вы передаете int безопасно. Вы не держите ссылку, а указываете на временный экземпляр варианта, который создан из int - который может быть вне области видимости.

РЕДАКТИРОВАТЬ: Я думаю, что вы пытаетесь сделать, это неправильно, учитывая, что boost::variant уже реализует operator== правильно. Например:

MyVariant testValue = 12;

MyVariant compareValue = 13;
MyVariant compareValue2 = 12;
MyVariant compareValue3 = "12";

std::cout << (compareValue == testValue) << std::endl;
std::cout << (compareValue2 == testValue) << std::endl;
std::cout << (compareValue3 == testValue) << std::endl;

Работает нормально - и я думаю, что это то, что вы пытаетесь достичь? Вы хотите проверить, что два варианта одинаково сопоставимы (?) Это будет работать до тех пор, пока все объекты в вашем варианте одинаково сопоставимы.

Около:

Но когда я вызываю applyEqualityVisitor(compareValue), он всегда возвращает false, независимо от того, что представляет собой CompareValue. Любая идея?

Я думаю, что вы неправильно поняли использование посетителей, оператор () вызывается с фактическим типом варианта, а не с параметром варианта (int в вашем примере).

РЕДАКТИРОВАТЬ: в коде

int testValue = 12;
CheckOneTypeEquality<MyVariant> equalityVisitor(testValue);

testValue преобразуется в MyVariant при создании экземпляра посетителя.

хороший пример ссылки повышения равенства

class are_strict_equals
    : public boost::static_visitor<bool>
{
public:

    template <typename T, typename U>
    bool operator()( const T &, const U & ) const
    {
        return false; // cannot compare different types
    }

    template <typename T>
    bool operator()( const T & lhs, const T & rhs ) const
    {
        return lhs == rhs;
    }

};

boost::variant< int, std::string > v1( "hello" );

boost::variant< double, std::string > v2( "hello" );
assert( boost::apply_visitor(are_strict_equals(), v1, v2) );

boost::variant< int, const char * > v3( "hello" );
assert( !boost::apply_visitor(are_strict_equals(), v1, v3) );

Другие вопросы по тегам