Правильно ли реализован этот посетитель?

Я внедряю посетителя, чтобы использовать его с библиотекой вариантов ускорения. Я хочу знать, правильно ли специализировать boost::static_visitor<> с константным ссылочным типом.

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

Есть проблемы со специализацией от boost::static_visitor<> до boost::static_visitor<const T&> ?

template<typename T>
struct my_visitor : public boost::static_visitor<const T&> {

    template<typename U> const T& operator()(U& u) const {
        // some code here .....
        return X<U>::get_some_t(); // finally return some T.
    }
};

person Eric Javier Hernandez Saura    schedule 06.11.2014    source источник
comment
Мне трудно понять ваш вопрос, даже прочитав вопрос пару раз. Не могли бы вы привести более полный пример того, что вы пытаетесь сделать?   -  person Mark B    schedule 06.11.2014
comment
@MarkB очень прост, я реализую посетителя в более сложном сценарии, который я показал в вопросе, и я получаю некоторые странные ошибки. Итак, чтобы отбросить некоторые возможности, я хочу знать, есть ли какие-либо проблемы со специализацией шаблона static_visitor с помощью const T&. Я ожидаю, что какой-нибудь эксперт даст мне ответ: Нет, это не должно вызывать у вас никаких проблем. Или, может быть: Да, когда вы это делаете, происходит (...). Спасибо за интерес заранее.   -  person Eric Javier Hernandez Saura    schedule 06.11.2014


Ответы (1)


Нет проблем, если вы не возвращаете ссылку на локальный/временный.

Кроме того, обязательно проверяйте действительность ссылки с течением времени (оно заканчивается, когда объект варианта уничтожается, то есть когда уничтожается сам вариант, или (!) при повторной инициализации).

Предыстория и объяснение

Вариант содержит объект "текущего" типа элемента, и вы можете прекрасно сослаться на этот объект. До тех пор, пока вариант не будет повторно инициализирован для другого типа элемента (в этом случае ссылка "просто" висит, точно так же, как если бы время жизни объекта, на который делается ссылка, закончилось).

Поэтому, если get_somet_t() возвращает T& или T const& (или что-то с подходящим неявным преобразованием), проблем нет.

В более простой обстановке позвольте мне продемонстрировать допустимые варианты:

variant<int, std::string> v1 = 42;

int& i1 = get<int>(v1); // returns by ref, valid
i1 *= 2;

// now v1 contains the updated integer value 84

Точно так же вы можете даже сделать варианты /просто ссылки/:

std::string s = "hello";
int answer = 42;

variant<int&, std::string&> v2(s);
get<std::string&>(v2) += " world"; // now s contains "hello world"

variant<int&, std::string&> v3(answer);
get<int&>(v3) *= 2; // now `answer` contains 84

Смотрите все Прямой эфир на Coliru


Демонстрация

Скажем еще по-другому, подойдет следующее:

struct A { std::string a_property; };
struct B { std::string b_field;    };

struct select_member : static_visitor<std::string&> {
    std::string& operator()(A& a) const { return a.a_property; }
    std::string& operator()(B& b) const { return b.b_field;    }
};

int main()
{
    variant<A,B> v = A { "some string" };

    apply_visitor(select_member(), v) += " suffix";

    std::cout << get<A>(v).a_property << "\n"; // prints "some string suffix"
}

Смотрите также Прямой эфир на Coliru.

person sehe    schedule 06.11.2014
comment
Добавлена ​​демонстрация, очень похожая на исходный случай, хотя и с неконстантными ссылками в разделе Демонстрация. - person sehe; 06.11.2014