boost::variant - Why a template parameter has higher precedence than a const string parameter

boost, boost-variant, c++, templates

Solution

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.

Problem

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; } ```

Original source