6

我在以下代码中目睹了我不理解的行为。关键是,如果我声明第二个重载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;
}
4

1 回答 1

6

你这里有const问题。

您将不是 const 对象传递给apply_visitor- 因此不是 const 对象成员传递给应用的访问者。所以在你的情况下是string&- 引用字符串类型。此模板与其完全匹配:

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

所以它被选中。此函数不完全匹配 - 它被跳过:

bool operator()(const string &other) const

当然,如果您提供该运算符:

bool operator()(string &other) const

那么它将被选中,因为在模板一之前考虑了非模板功能。

所以解决方案是:要么在您的访问者中提供采用字符串引用(不是 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 具有很强的意义。

于 2012-11-10T07:34:42.413 回答