I am witnessing a behavior in the following code that I don’t understand. The point is that if I declare the second overload of operator() like either of the following:
bool operator()(T other) const
bool operator()(const T &other) const
The output of program is:
string
But if I use the following declaration:
bool operator()(T &other) const
The output will be:
other type
Can someone please explain why operator()(const string &other) is not being called in the latter case?
#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;
}
You have
constproblem here.You are passing not const object to
apply_visitor– so not const object members are passed to applied visitor. So in your case it isstring&– reference to string type. This template is exact match for it:So it is selected. This function is not exact match – it is skipped:
Of course if you provide that operator:
then it would be selected, since non template function are considered before template one.
So solution is: either provide method in your visitor which takes string reference (not const) – or pass const variant to apply…
First solution – remove const from string operator:
Second solution – pass const object:
Third solution – add const specifier to general visitor:
Solutions 1st and 3rd are the better than 2nd – you should pass consistent visitor to your variant, const has strong meaning when compiler has to select appropriate function.