boost :: variable — почему параметр шаблона имеет более высокий приоритет, чем параметр const string

Я наблюдаю поведение в следующем коде, которое я не понимаю. Дело в том, что если я объявлю вторую перегрузку operator() как один из следующих:

bool operator()(T other) const
bool operator()(const T &other) const

Выход программы:

строка

Но если я использую следующую декларацию:

bool operator()(T &other) const

Выход будет:

другой тип

Может кто-нибудь объяснить, почему operator()(const string &other) не вызывается в последнем случае?

#include "boost/variant/variant.hpp"#include "boost/variant/apply_visitor.hpp"
using namespace std;
using namespace boost;

typedef variant<string, int> MyVariant;class StartsWith
: public boost::static_visitor<bool>
{
public:
string mPrefix;
bool operator()(const string &other) const
{
cout << "string" << endl;
return other.compare(0, mPrefix.length(), mPrefix) == 0;
}
template<typename T>
bool operator()(T &other) const
{
cout << "other type" << endl;
return false;
}
StartsWith(string const& prefix):mPrefix(prefix){}
};

int main(int argc, char **argv)
{
MyVariant v(string("123456"));
apply_visitor(StartsWith("123"), v);
return 0;
}

6

Решение

У тебя есть const проблема здесь.

Вы передаете не постоянный объект apply_visitor — поэтому неконстантные члены объекта передаются посетителю. Так что в вашем случае это string& — ссылка на тип строки. Этот шаблон точно соответствует ему:

template<typename T>
bool operator()(T &other) const

Так и выбрано. Эта функция не является точным соответствием — она ​​пропущена:

bool operator()(const string &other) const

Конечно, если вы предоставите этого оператора:

bool operator()(string &other) const

тогда он будет выбран, так как не шаблонная функция рассматривается перед первым шаблоном.

Решение таково: либо предоставьте посетителю метод, который принимает строковую ссылку (не const), либо передайте константный вариант для применения …

Первое решение — удалить const из строкового оператора:

bool operator()(/*const*/ string &other) const
//              ^^^^^^^^^ remove it

Второе решение — передать объект const:

const MyVariant& cv = v;
apply_visitor(StartsWith("123"), cv);
//                               ^^ const object passed here

Третье решение — добавить спецификатор const для общего посетителя:

template<typename T>
bool operator()(const T &other) const
//              ^^^^^

Решения 1-го и 3-го лучше, чем 2-го — вы должны передать согласованный посетитель для вашего варианта, const имеет сильное значение, когда компилятор должен выбрать соответствующую функцию.

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]