0

通过 Mex 开展一个关于 C++ 和 Matlab 合作的大型项目,我们目前正与我们的一个单身人士作斗争。

该类是在预处理期间通过宏生成的,因此看起来有点奇怪。

class AdditionalOperation { 
private: 
    const std::string* val; 
    typedef std::map<std::string, const std::string*> StringMap; 

    static StringMap& getStringToPointerMap() 
    { 
        static StringMap map; 
        return map; 
    } 

    static boost::mutex& getMutex()
    { 
        static boost::mutex mutex; 
        return mutex; 
    } 

    AdditionalOperation(const std::string* s)
        :val(s) 
    {} 
private: 
    static std::string* none_string() 
    { 
        static std::string s = "none"; 
        static int count = 0; 
        boost::mutex::scoped_lock lock(getMutex()); 
        if(count++ == 0) { 
            getStringToPointerMap().insert(std::make_pair(s,&s)); 
        } 
        return &s; 
    } 
public: 
    static AdditionalOperation none() 
    { 
        return AdditionalOperation(none_string()); 
    } 

private: 
    static std::string* norm_string() 
    {   
        static std::string s = "norm"; 
        static int count = 0; 
        boost::mutex::scoped_lock lock(getMutex()); 
        if(count++ == 0) { 
            getStringToPointerMap().insert(std::make_pair(s,&s)); 
        } 
        return &s; 
    } 
public: 
    static AdditionalOperation norm() 
    { 
        return AdditionalOperation(norm_string()); 
    } 
private: 
    static void prepare() 
    { 
        none(); 
        norm(); 
    } 
public: 
    static AdditionalOperation fromString(std::string s) 
    { 
        static int count = 0; 
        if(count++ == 0) 
            prepare(); 
        boost::mutex::scoped_lock lock(getMutex()); 
        StringMap& map = getStringToPointerMap(); 
        StringMap::iterator location = map.find(s); 
        if(location == map.end()) { 
            throw UnknownEnumValue(s); 
        } 
        return AdditionalOperation(location->second); 
    } 

    std::string toString() const 
    { 
        return *val; 
    }

    bool operator==(const AdditionalOperation& other) const 
    { 
        return val == other.val; 
    } 

    bool operator!=(const AdditionalOperation& other) const 
    { 
        return !(*this == other); 
    } 
};

所有这些代码都是从这一行生成的(通过如上所述的宏):

DECLARE_SENUM(AdditionalOperation, none, norm);

这是一个很好的界面,我们希望继续使用。

我们想使用这个类作为枚举的替代品,因为我们需要将它们从字符串转换为字符串。在这个类中,我们有 2 个“枚举”成员,即 norm 和 none。

现在我们添加了一些日志记录,并确定 none_string 和 norm_string 函数内的插入操作被调用了两次,即使我们的计数器应该阻止这种情况。

我们尝试过的一些事情:

  • 我们正在使用动态库,但使用 -rdynamic 并没有帮助。
  • 当我们打印静态变量的地址时,我们可以清楚地看到它们不同。
  • 此类位于动态库中,该动态库又与 mex 文件链接。此 mex 文件正在由另一个 mex 文件通过 dlopen 动态加载。

我们在想,由于动态库,可能该类的多个实例被声明并处于活动状态。但是我们也使用了其他类型的没有任何问题迹象的单例。

我希望它足够清楚,可以随时提供额外的信息或澄清!

提前致谢!

4

1 回答 1

1

很明显,你把问题复杂化了。

std::string const& to_string(MyEnum e) {
    static std::string const First = "First";
    static std::string const Second = "Second";

    switch(e) {
    case MyEnum::First: return First;
    case MyEnum::Second: return Second;
    }

    throw std::runtime_error("Unknown enum value");
}

如果不是更好更快,也会起作用。

于 2013-03-04T16:13:50.937 回答