我在以下代码中看到一个我不理解的行为。关键是,如果我声明 operator()
的第二个重载,如下所示:
bool operator()(T other) const
bool operator()(const T &other) const
程序的输出是:
string
但是如果我使用下面的声明:
bool operator()(T &other) const
输出将是:
other type
有人可以解释一下为什么在后一种情况下没有调用 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;
}
最佳答案
这里有const
问题。
您将非常量对象传递给 apply_visitor
- 因此非常量对象成员将传递给应用的访问者。所以在你的情况下它是 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 具有很强的意义。
关于c++ - boost::variant - 为什么模板参数的优先级高于 const 字符串参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13320145/