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 const
problem 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 is string&
- reference to string type. This template is exact match for it:
template<typename T>
bool operator()(T &other) const
So it is selected. This function is not exact match - it is skipped:
bool operator()(const string &other) const
Of course if you provide that operator:
bool operator()(string &other) const
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:
bool operator()(/*const*/ string &other) const
// ^^^^^^^^^ remove it
Second solution - pass const object:
const MyVariant& cv = v;
apply_visitor(StartsWith("123"), cv);
// ^^ const object passed here
Third solution - add const specifier to general visitor:
template<typename T>
bool operator()(const T &other) const
// ^^^^^
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With