默认容器参数

Posted

技术标签:

【中文标题】默认容器参数【英文标题】:Default container arguments 【发布时间】:2012-05-17 17:06:28 【问题描述】:

当我调用不带参数的函数 bat 时,以下标头可以按预期与注释部分一起使用:

class Test

 public:

  void bat(std::vector<int> k = std::vector<int>()) 
  //void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) 

;

但是当我尝试在标题中使用 cat 函数时:

class Test

 public:

  void bat(std::vector<int> k = std::vector<int>()) 
  void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) 

;

我明白了:

test.h:14: error: expected ',' or '...' before '>' token
test.h:14: error: wrong number of template arguments (1, should be 4)
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_map.h:92: error: provided for 'template<class _Key, class _Tp, class _Compare,\
 class _Alloc> class std::map'
test.h:14: error: default argument missing for parameter 2 of 'void Test::cat(std::map<int, std::vector<int, std::allocator<int> >, std::less<int>, std::all\
ocator<std::pair<const int, std::vector<int, std::allocator<int> > > > >, std::vector<int, std::allocator<int> >)'

怎么会?有没有简单的解决方法?希望不需要在接口中更改指针类型?

这是我的完整标题:

#ifndef TEST_H
#define TEST_H

#include <map>
#include <vector>
#include <sstream>
#include <iostream>

class Test

 public:

  //void bat(std::vector<int> k = std::vector<int>()) 
  void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >()) 

;


#endif

所以所有正确的包括都在那里。我的 GCC 版本非常过时(不是在家里,我也在家里试试)——但在工作中它是 4.1.2

【问题讨论】:

闻起来像 GCC 错误 -- fails with 4.3.4、works with 4.5.1。你用的是什么版本? 这编译得很好,你是否包含&lt;map&gt; 错误信息将指向 4.1.2,其中包含 &lt;map&gt; 这在 GCC 4.6.3 上编译得很好。 @Mat,是的,这是 gcc 的 4.1.2 版 - 你知道这是什么错误,或者我可以在哪里阅读更多相关信息吗?另外..如果我无法升级编译器,是否有一个指针可以解决这个问题? 【参考方案1】:

代码看起来不错,但在 gcc 4.3.4 上失败,请参阅here,但在 4.6 之后编译良好(我尚未测试 4.4 或 4.5)。所以看起来解决方法是使用更新的 gcc。

#include <map>
#include <vector>

class Test

 public:

  void bat(std::vector<int> k = std::vector<int>()) 
  void cat(std::map<int, std::vector<int> > k = std::map<int, std::vector<int> >
()) 

;

int main() 


关于默认参数,最好完全放弃它们:

class Test 
 public:

  void bat(std::vector<int> k) 
  void bat() 
  void cat(std::map<int, std::vector<int> > k) 
  void cat() 
;

否则,您将默认参数耦合到接口,这意味着您无法在不重新编译所有客户端代码的情况下更改它们。

【讨论】:

真实情况是我有一个函数,它在是否需要最终容器方面有所不同..重载有很多重复的代码,维护起来很烦人,但我意识到如果可选的最终容器为空,它会无缝地流过成为没有它的版本,所以我合并了两个重载并将最终容器默认参数化为一个空容器。我认为一种解决方法可能是在没有它的情况下提供重载,但只是将带有空容器的调用转发到唯一的实现。 @PalaceChan 是的,这听起来是一个合理的解决方案。【参考方案2】:

您发布的代码看起来不错,所以我将打开我的 Psychic Debugger 模块。

你有没有:

#include <vector>

...在你的标题中?

【讨论】:

是的,我做到了,这看起来越来越像人们谈论的那个错误了。【参考方案3】:

从这里的其他帖子看来,这可能是编译器问题,在这种情况下,您可以通过使用 typedef 而不是直接映射类型来解决它。

#include <vector>
#include <map>

class Test

 public:
  typedef std::map<int, std::vector<int> > MyMap;

  void bat(std::vector<int> k = std::vector<int>()) 
  void cat(MyMap k = MyMap()) 

;

int main()


【讨论】:

【参考方案4】:

这是 C++ 核心缺陷报告 325 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#325

GCC 4.4 实现了 DR 的建议(但尚未正式)解决方案,请参阅 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57#c36

【讨论】:

以上是关于默认容器参数的主要内容,如果未能解决你的问题,请参考以下文章

WebUploader参数

docker笔记:docker容器通信参数 --link参数介绍

Kafka学习篇1:Docker安装Kafka(单机默认参数版,依赖于Zookeeper)

docker run 默认工作目录 -w 参数

docker run 默认工作目录 -w 参数

docker run 命令参数