我正在见证以下代码中的一个我不理解的行为。关键是如果我声明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;
}
答案 0 :(得分: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
然后它会被选中,因为非模板函数在模板1之前被考虑。
所以解决方案是:在访问者中提供带有字符串引用(而不是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具有强烈的意义。