【问题标题】:How to provide map with a comparator that requires static data?如何为地图提供需要静态数据的比较器?
【发布时间】:2015-02-03 16:58:03
【问题描述】:

我正在尝试提供带有需要静态数据的比较器的地图。但是,以下方法失败了,因为(我的编译器告诉我)C++ 不接受静态构造函数:

struct MyOrder {
    static std::map<std::string, int> m_specialOrder;
    static MyOrder() {
        m_specialOrder["First"] = 1;
        m_specialOrder["Second"] = 2;
        m_specialOrder["Third"] = 3;
    }
    bool operator() (const std::string& a, const std::string& b)
    {
        std::map<std::string, int>::iterator x = m_specialOrder.find(a);
        if(x == m_specialOrder.end()) return false;
        std::map<std::string, int>::iterator y = m_specialOrder.find(b);
        if(y == m_specialOrder.end() || x->second < y->second) return true;
        return false;
    }
};

我想要静态构造之类的东西,因为我只需要 m_specialOrder 映射的一个实例,而且我不希望每次使用比较器或定义使用它的映射时都对其进行初始化。

我的目标是能够在如下地图上使用我的特殊排序:

std::map<std::string, double, MyOrder> mySpecialMap;

我怎样才能做到这一点?

【问题讨论】:

  • 你为什么要让你的构造函数变成静态的?
  • 我希望您不要考虑在地图处于活动状态时更改比较功能中的静态数据。更改地图中键的顺序会严重破坏地图。
  • 正如错误所暗示的,static 构造函数在 C++ 中没有意义。你想在那里做什么?
  • 不,不想更改静态数据。我只是想防止数据在每次使用该结构时被重新实例化。在问题中添加了一段来澄清这一点。

标签: c++ stl comparator


【解决方案1】:

在 C++98 中你可以这样做:

把它放在你的头文件中:

static std::map<std::string, int> m_specialOrder;
static std::map<std::string, int> initSpecialOrder();

把它放在你的 cpp 文件中:

std::map<std::string, int> MyOrder::m_specialOrder =
    MyOrder::initSpecialOrder();

std::map<std::string, int> MyOrder::initSpecialOrder() {
    std::map<std::string, int> res;
    res["First"] = 1;
    res["Second"] = 2;
    res["Third"] = 3;
    return res;
}

在 C++11 及更高版本中,您可以删除 initiSpecialOrder,并改用花括号初始化器:

std::map<std::string, int> MyOrder::m_specialOrder = {
    {"First", 1}, {"Second", 2}, {"Third", 3}
};

【讨论】:

  • 另外,您可以在源文件中本地定义 init 函数(静态或无名命名空间)
  • 等等,所以 initSpecialOrder() 需要返回一个 std::map<:string int> 对吧?并且对 initSpecialOrder 的调用需要在 main() 开始之后和使用比较器之前的某个时间发生在执行路径中,对吧?
  • @feetwet 第一部分是“是”,第二部分是“否”。事实上,initSpecialOrder 需要返回 std::map&lt;string,int&gt;,现在已修复。但是,您无需在任何地方进行此调用。 C++ 编译器会为您完成它,因为它是初始化程序 std::map&lt;std::string, int&gt; MyOrder::m_specialOrder = MyOrder::initSpecialOrder(); 的一部分,您只需将它放在 C++ 文件之一中的任何位置。
  • 啊哈——这似乎工作(或至少编译)!看起来我们要么需要从 initSpecialOrder 调用中返回 m_specialOrder,要么如果它作为一个 void 函数工作,就这样声明它?
  • @feetwet 糟糕,这是另一个复制/粘贴错误。我现在修好了。
【解决方案2】:

你不能有一个static 构造函数——这没有意义,只需使用:

 MyOrder() {
    m_specialOrder["First"] = 1;
    m_specialOrder["Second"] = 2;
    m_specialOrder["Third"] = 3;
}

【讨论】:

  • 由于m_specialOrder 是静态的,因此您最终会比您应该更频繁地运行此代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多