2

当使用 std::pair 或 std::map 时,我们需要使用“first”或“second”来访问数据。但是对于其他没有编写此代码的同事来说,这两个变量名称并没有明确的含义。因此,如果我们可以为“first”或“second”设置别名,它将大大提高可读性。

例如下面的代码

static const std::map<std::string, std::pair<std::string, PFConvert>> COMM_MAP =
{  // keyword->         (caption,                   function)
{std::string("1"), {std::string("Big5 to Utf16LE"), &FileConvert_Big5ToUtf16LE}},
{std::string("2"), {std::string("Utf16LE to Utf8"), &FileConvert_Utf16LEToUtf8}},
{std::string("3"), {std::string("Utf8 to Big5"), &FileConvert_Utf8ToBig5}}
};

auto iterToExe = COMM_MAP.find(strTransType);
iterToExe->second.second();

iterToExe->second.second();可读性确实很差。

所以我尝试使用继承来给出别名,如下所示

template<typename PFComm>
class CCommContent : public std::pair<std::string, PFComm>
{
public:
    std::string &strCaption = std::pair<std::string, PFComm>::first;
    PFComm &pfComm = std::pair<std::string, PFComm>::second;
};

template<typename PFComm>
class CCommPair : public std::pair<std::string, CCommContent<PFComm>>
{
public:
    std::string &strPattern = std::pair<std::string, CCommContent<PFComm>>::first;
    CCommContent<PFComm> commContent = std::pair<std::string,CCommContent<PFComm>>::second;
};

template<typename PFComm>
class CCommMap : public std::map<std::string, CCommContent<PFComm>, std::less<std::string>, std::allocator<CCommPair<PFComm>>>
{};

但这涉及到另一个问题:我必须声明所有的ctors,虽然我可以调用基本的ctors,但它似乎仍然不是一个聪明的方法。我只想制作别名。

一个简单的方法是使用宏......但它绕过了类型检查。使用嵌套结构时,调试时可能是一场噩梦。

任何建议或讨论将不胜感激。

4

3 回答 3

2

一些类型定义和访问器函数怎么样?

using CommEntry = std::pair<std::string, PFConvert>;

std::string const & getCaption(CommEntry const & e) { return e.first; }
PFConvert const & getFunction(CommEntry const & e) { return e.second; }

现在你可以说:

auto it =  COMM_MAP.find(strTransType);
if (it != COMM_MAP.end())
{
    auto & c = getCaption(it->second);
    auto & l = getLabel(it->second); 
    // ...
}

如果您稍后更改类型的详细信息,则只需调整访问器功能。

于 2014-03-06T08:12:46.577 回答
2

为什么不简单地使用自己struct的元素名称呢?

struct MyPair {
    std::string strCaption;
    PFComm pfComm;
};

使用 C++11,您可以轻松地创建它的新对象:

MyPair{std::string("Big5 to Utf16LE"), &FileConvert_Big5ToUtf16LE}}

如果您定义自己的operator<,则可以将std::set工作作为地图:

bool operator<(const MyPair& a, const MyPair& b) {
    return a.strCaption < b.strCaption;
}

typedef std::set<MyPair> MyPairMap;

当然,您可以嵌套自定义结构以形成更复杂的嵌套对,尽管在您的情况下,您可能需要考虑使用扁平三元组:

struct CommMapEntry {
     std::string number;
     std::string caption;
     PFComm pfComm;
};
bool operator<(const MyPair& a, const MyPair& b) {
    return a.number<b.number;
}
static const std::set<CommMapEntry> COMM_MAP;
于 2014-03-06T08:19:01.697 回答
1

好吧,在 c++11 中,我们可以using base::base在派生类中使用基本 ctor。但请注意,vs2013 不符合此要求。g++4.8 做。

于 2014-03-11T08:54:01.773 回答