【问题标题】:Non-member operator as private member of foreign class非会员运营商作为外国类的私人会员
【发布时间】:2013-08-30 23:46:10
【问题描述】:

是否可以有一个像这样的非会员运营商

bool operator==(const std::string &l, const Token r)

作为不相关类Interpreter 的私有成员函数? 我以明显的方式尝试了它,但它不起作用(参数太多)。 我知道,标题“非成员函数 [...] 作为成员”已经说反了,但是有没有比函数更好的方法

bool isToken(const std::string &l, const Token r)

进行依赖于Interpreter 的(非静态)成员的比较?

Interpreter 之外无法将Tokens 与strings 进行比较。

一些进一步的信息:令牌是一个枚举,比较取决于Interpreter 构造时设置的语言。

【问题讨论】:

  • 什么是 Token,如果 Token 是 LHS,== 将如何工作?
  • Token 是一个像 KEYWORD_ELSE 或 CONDITION_ALWAYS 这样的枚举。 KEYWORD_ELSE == "else" 对于“英语”口译员应该为真,KEYWORD_ELSE == “sonst”对于“德语”口译员应该为真。
  • 另外,如果 == 运算符是在 Intepreter 中定义的,您如何想象语法看起来像?或者您要求的运算符只能在解释器的上下文中工作,即用于解释器的成员方法?
  • 与其将标记与字符串进行比较,您是否可以将字符串转换为标记(在解释器的上下文中),然后将生成的标记相互比较?
  • 您的程序是否需要动态绑定到解释器,或者您可以假设您的程序在其持续时间内以单一语言模式运行?

标签: c++ class operator-keyword member non-static


【解决方案1】:

无法按照您想要的方式制作operator == 的版本。它不能变成静态的。如果它是一个成员,那么它必须有一个参数。

如果您愿意“重复代码”,那么您可以使用命名空间来玩花样。您的通用解释器可以是一个模板,它将特定语言的派生类作为模板参数。它反过来根据特定语言的标记调用模板化的operator==

template <typename TOKEN>
bool operator == (const std::string &l, const TOKEN token) {
    return token == l;
}

// Language specific interpreters inherit from this template
template <typename LANG>
class Interpreter {
public:
    void interpret () {
        std::string s("hi");
        if (s == LANG::KEYWORD_ELSE) {}
    }
};

Interpreter 的每个特定语言的子类都位于特定语言的命名空间中。该实现重复关键字的枚举,但在其他方面遵循模板实现。

namespace Lang0 {
    class Interpreter : public ::Interpreter<Lang0::Interpreter> {
        //...
    public:
        enum Token { KEYWORD_ELSE, //...
                   };
        static Interpreter & instance () {
            static Interpreter interpreter;
            return interpreter;
        }
    };
}

namespace Lang1 {
    class Interpreter : public ::Interpreter<Lang1::Interpreter> {
        //...
    public:
        enum Token { KEYWORD_ELSE, //...
                   };
        static Interpreter & instance () {
            static Interpreter interpreter;
            return interpreter;
        }
    };
}

每个命名空间还为operator== 提供了特定于语言的实现,以将字符串与特定于语言的标记进行比较。

namespace Lang0 {
    bool operator == (const Interpreter::Token token, const std::string &l) {
        //...
    }
}

namespace Lang1 {
    bool operator == (const Interpreter::Token token, const std::string &l) {
        //...
    }
}

然后,当Interpreter 的模板实现调用operator== 的模板版本时,它会解析为相应语言特定命名空间中的语言特定实现。

【讨论】:

  • 很遗憾,代码复制也不起作用。解释器将带有翻译的给定数据库加载到地图中。是否有 C++ 不允许这样做的原因,或者它被遗忘/不是故意的?
  • 我不知道如何回答你的问题。我的印象是,因为您想将operator== 放置为Interpreter 的成员,所以比较只会在Interpreter 实例的上下文中发生。这就是为什么我认为上述解决方案对你有用。我曾假设英语口译员与德语口译员是不同的实例。
  • 所支持的语言在编译时是未知的。我可能会让用户定义自定义语言并让他为他的程序选择它。类似Interpreter tab1('user1.lang');
  • 我的解决方案仍然有效。相反,命名空间可以基于语言命名语言索引(Lang0Lang1)。只要您愿意限制可以支持的语言数量,此方法就可以使用。
  • 不,这比“匹配(令牌,字符串)”的更好方法更复杂,更无用的黑客限制。
【解决方案2】:

由于比较是由 Interpreter 的非静态成员(例如 is_equal())进行的,因此您需要三个对象来进行比较:Interpreter、字符串和 Token。

如果您知道在比较时恰好有一个有效的解释器对象实例,您可以让这个实例静态访问,例如

bool operator==(const std::string &l, const Token r)
{
   return Interpreter::instance().is_equal(l, r);
}

其中静态成员 instance() 返回执行工作的解释器对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 2011-07-06
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2021-01-02
    • 2011-09-18
    相关资源
    最近更新 更多