包装cstrings(const char *)以便能够将它们存储到STL容器中

时间:2013-05-30 13:21:32

标签: c++ boost stl typetraits

我需要将一些不同类型的变量存储到stl容器中(在本例中为std :: map)。虽然,当这个变量是一个字符串时,我不能使用std :: string,因为内存使用很关键。

因此,我需要找到一种方法将所有字符串存储为cstrings(const char *)到该映射中。所以我尝试编写一些类来保存值:

template<class T>
class ValueHolder {
private:
    T value;
public:
    ValueHolder(const T &argValue) :
        value(argValue) {
    }
    const T& getValue() {
        return value;
    }
    ~ValueHolder() {}
};

template<>
class ValueHolder<const char*> {
private:
    char* value;

public:
    ValueHolder(const char* argValue) {
        value = strdup(argValue);
        std::cout << "constructing ValueHolder(const char*) " << value << std::endl;
    }
    ValueHolder(const ValueHolder<const char*> &argExtension) {
        value = strdup(argExtension.value);
    }
    const char* getValue() const {
        std::cout << "returning ValueHolder(const char*) " << value << std::endl;
        return value;
    }
    ~ValueHolder() {
        if(value != NULL)
            free(value);
    }
};

然后,我宣布了std :: map

std::map<ValueType::Type, boost::any> extensions_;

以下是允许设置和检索它的函数(使用boost :: any):

template<class Type>
Type getExtension(const ValueType::Type &argValueType) const {
    std::map<ValueType::Type, boost::any>::const_iterator it = extensions_.find(argValueType);
    if(it != extensions_.end()) {
        switch(argValueType) {
        case ValueType::VAL_INT:
            if(boost::is_same<EnumFooType::Type, Type>::value) {
                return (boost::any_cast<ValueHolder<Type> >((*it).second)).getValue();
            } else {
                std::cout << "Wrong type for this value" << std::endl;
            }
            break;
        case ValueType::VAL_STR_1:
        case ValueType::VAL_STR_2:
            if(boost::is_same<const char *, typename boost::decay<Type>::type>::value) {
                return (boost::any_cast<ValueHolder<Type> >((*it).second)).getValue();
            } else {
                std::cout << "Wrong type value for this Holder" << std::endl;
            }
            break;
        default:
            std::cout << "Unhandled type of value, skipping..." << std::endl;
            break;
        }

    }
    throw ValueNotFoundException("Could not find a value for this subscriber extension");
}

template<class T>
void setExtension(const ValueType::Type &argExtensionType , T argExtensionValue) {
    boost::any any_value;
    switch(argExtensionType) {
    case ValueType::VAL_INT:
        if(boost::is_same<EnumFooType::Type, T>::value) {
            any_value = ValueHolder<T>(argExtensionValue);
            extensions_[argExtensionType] = any_value;
        } else {
            std::cout << "Wrong type value for Billing subscriber extension" << std::endl;
        }
        break;
    case ValueType::VAL_STR_1:
    case ValueType::VAL_STR_2:
        if(boost::is_same<const char *, typename boost::decay<T>::type>::value) {
            any_value = ValueHolder<T>(argExtensionValue);
            extensions_[argExtensionType] = any_value;
        } else {
            std::cout << "Wrong type for this value, it should be a cstring!" << std::endl;
        }
        break;
    default:
        std::cout << "Unhandled value type, skipping..." << std::endl;
        break;
    }
}

问题是当指定的类型是cstring(const char *)时返回的值不正确,这是我的测试程序输出:

  

构造ValueHolder(const char *)FR

     

良好的枚举值:)

     

返回ValueHolder(const char *)FR

     

!!! ERROR !!!值是 而不是FR

如果需要,我稍后会提供一个在线测试程序,但liveworkspace和coliru目前都已关闭。

感谢任何帮助,提前谢谢!

编辑:以下是测试计划:http://codepad.org/zbLQDAiS

EDIT2:这里我用来测量const char *和std :: string的内存使用情况的程序:http://coliru.stacked-crooked.com/view?id=3b3c4d7ce1d8d1400e3f6e45f75040dc-9294698a18feab30c803b17d837ba467

我只是让它成为一个守护进程,并使用top来查看进程内存使用情况。

EDIT3:这是一篇有趣的文章,展示了相同的结果:http://jovislab.com/blog/?p=76

0 个答案:

没有答案