M ++数据库字段的C ++全局映射

时间:2013-07-16 21:44:14

标签: c++ mongodb boost singleton

我有一个应用程序使用mongodb作为后端数据库,并希望集中在mongo集合中使用的字段名称,以便在C ++方面进行访问。字段名称用于应用程序的各个部分(序列化,查询等),我不希望在所有这些不同的位置实际硬编码字段名称以便于维护。

最初想到使用单身人士,但我宁愿不使用单身人士。我还玩弄了使用boost fusion来创建类型到字段名称的映射的想法,但这些类型基本上都是空结构。对方法的想法?

2 个答案:

答案 0 :(得分:0)

使用带序列化/反序列化的枚举 - 每个集合一个枚举是有意义的:

#include <string>
#include <iostream>
#include <boost/bimap.hpp>

template<typename def, typename inner = typename def::type>
class safe_enum : public def
{
    inner val;

public:
    typedef typename def::type type;
    safe_enum(type v) : val(v) {}
    inner underlying() const { return val; }

    friend bool operator == (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val == rhs.val; }
    friend bool operator != (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val != rhs.val; }
    friend bool operator < (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val < rhs.val; }
    friend bool operator <= (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val <= rhs.val; }
    friend bool operator > (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val > rhs.val; }
    friend bool operator >= (const safe_enum & lhs, const safe_enum & rhs) { return lhs.val >= rhs.val; }
};

class some_collection_fields_def
{
public:
    enum type { invalid, somename, anothername, morenames };
};

class some_collection_fields
    :
        public safe_enum< some_collection_fields_def >
{
public:
    typedef safe_enum< some_collection_fields_def > BaseType;
public:
    some_collection_fields( type v )
        :
            BaseType( v )
    {}
    some_collection_fields( const std::string& v )
        :
            BaseType( invalid )
    {
        *(this) = v;
    }
    some_collection_fields& operator =( const std::string& in )
    {
        string_bimap_type::right_map::const_iterator cit = string_bimap.right.find( in );
        if ( cit == string_bimap.right.end() )
        {
            throw std::domain_error( std::string( __func__ ) + ": Failed to convert from [" + in + "]" );
        }
        (*this) = cit->second;
        return *this;
    }
    const std::string& as_string() const
    {
        string_bimap_type::left_map::const_iterator cit = string_bimap.left.find( this->underlying() );
        if ( cit == string_bimap.left.end() )
        {
            throw std::range_error( std::string( __func__ ) + ": Undefined value [" + std::to_string( this->underlying() ) + "]" );
        }
        return cit->second;
    }
private:
    typedef boost::bimap< type, std::string > string_bimap_type;
    static string_bimap_type string_bimap_init()
    {
        string_bimap_type tmp_string_bimap;
        tmp_string_bimap.insert( string_bimap_type::value_type( somename, "somename" ) );
        tmp_string_bimap.insert( string_bimap_type::value_type( anothername, "anothername" ) );
        tmp_string_bimap.insert( string_bimap_type::value_type( morenames, "morenames" ) );
        return tmp_string_bimap;
    }
    static string_bimap_type string_bimap;
};

some_collection_fields::string_bimap_type some_collection_fields::string_bimap = some_collection_fields::string_bimap_init();

std::ostream& operator <<( std::ostream& out, const some_collection_fields& in )
{
    out << in.as_string();
    return out;
}

int main()
{
    {
        some_collection_fields field = some_collection_fields::somename;
        std::cout << field << std::endl;
        std::cout << field.as_string() << std::endl;
        std::cout << field.underlying() << std::endl;
    }
    {
        some_collection_fields field( "anothername" );
        std::cout << field << std::endl;
        std::cout << field.as_string() << std::endl;
        std::cout << field.underlying() << std::endl;
    }
}

编译:

g++ -std=c++0x -o 17687554.a1 17687554.a1.cpp

输出:

$ ./17687554.a1 
somename
somename
1
anothername
anothername
2

注意:

  1. safe_enum来自here
  2. 你可以用模板概括这个

答案 1 :(得分:0)

我采用了一种使用增强融合和枚举的方法。

enum ActivitySchemaEnum
{
  DEFINITION,
  NAME,
  STATE,
  START,
  END
};

template <ActivitySchemaEnum ACTSCHEMA_V>
struct Field;

typedef boost::fusion::map<
  boost::fusion::pair<Field<DEFINITION>, char const*>,
  boost::fusion::pair<Field<NAME>, char const*>,
  boost::fusion::pair<Field<STATE>, char const*>,
  boost::fusion::pair<Field<START>, char const*>,
  boost::fusion::pair<Field<END>,   char const*>
> actinst_schema;

actinst_schema const ActivitySchema(
  boost::fusion::make_pair<Field<DEFINITION> >("definition"),
  boost::fusion::make_pair<Field<NAME> >("name"),
  boost::fusion::make_pair<Field<STATE> >("state"),
  boost::fusion::make_pair<Field<START> >("start"),
  boost::fusion::make_pair<Field<END> >("end")
);

然后在客户端代码中我调用(简单调用,但你明白了。)

const char* myFieldName = boost::fusion::at_key<Field<DEFINITION> >(ActivitySchema);

客户端的使用有点冗长,但我认为它实际上非常自我描述你在做什么。