如何制作特定类的成员函数或变量的别名(如 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->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<
,则可以将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 类的成员函数? (正文中的详细解释)