如何制作特定类的成员函数或变量的别名(如 STL 容器)

Posted

技术标签:

【中文标题】如何制作特定类的成员函数或变量的别名(如 STL 容器)【英文标题】:How to make aliases of member function or variable of specific class(like an STL container) 【发布时间】:2014-04-08 17:42:42 【问题描述】:

当使用 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-&gt;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,但它似乎仍然不是一个聪明的方法。我只想做别名。

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

【参考方案2】:

为什么不简单地将您自己的struct 与您自己的元素名称一起使用?

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

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

MyPairstd::string("Big5 to Utf16LE"), &FileConvert_Big5ToUtf16LE

如果您定义自己的operator&lt;,则可以将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;

【讨论】:

这么简单的方法!但是因此我必须编写一个 caster(string -> CommMapEntry) 来使用 set::find() (似乎是一个奇怪的转换?)。但它仍然比用 std::map 重写 ctor 有效得多。非常感谢!【参考方案3】:

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

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); 
    // ...

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

【讨论】:

虽然不是别名(我喜欢用“.”或“->”调用成员风格),但仍然是一种经济的好方法。非常感谢。

以上是关于如何制作特定类的成员函数或变量的别名(如 STL 容器)的主要内容,如果未能解决你的问题,请参考以下文章

面向对象:类的成员---只是特定(类的)命名空间的全局变量(函数)而已

如何访问不在基类中的派生类中的 STL 类的成员函数? (正文中的详细解释)

如何创建引用特定函数的函数类型的类型别名

打印/修改类对象的特定成员变量,其类定义列表(STL)包含的元素类型

如何检测类中是不是存在特定的成员变量?

STL之complex