boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级

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

本文关键字:参数 优先级 字符串 变体 为什么 boost const      更新时间:2023-10-16

我目睹了以下代码中我不理解的行为。关键是,如果我像以下任何一个声明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;
}

您在这里有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
//              ^^^^^ 

解决方案第一和第三是比第二个更好的 - 您应该将一致的访问者传递给您的变体,当编译器必须选择适当的功能时,const具有很强的含义。