使用默认参数提升list_of

时间:2014-08-20 10:18:25

标签: c++ visual-c++ boost

我遇到以下构造的问题:

  struct A {
    int min_version;
    int max_version;
    std::vector<int> nodes;

    A(std::vector<int> _nodes, int _min_version = 0, int _max_version = MAXINT)
      : nodes(_nodes), min_version(_min_version), max_version(_max_version)
    {};

  };

  static std::vector<A> a = list_of<A>
    (list_of (1) (2))
   ;

我遇到编译器错误,2个重载都不能转换所有参数类型(Visual Studio 2013)。但是,当我为一个或两个默认参数添加值时,它编译得很好:

  static std::vector<A> a = list_of<A>
    (list_of (1) (2), 1)
   ;

那么,使两个默认参数都起作用的技巧是什么?

1 个答案:

答案 0 :(得分:1)

当您将list_of<A>(...)替换为list_of(A(...))时,单参数版本的问题变得更加明显:编译器错误变为(GCC):

list.cc: In function ‘int main()’:
list.cc:18:30: error: call of overloaded ‘A(boost::assign_detail::generic_list<int>&)’ is ambiguous
   list_of (A (list_of (1) (2)));
                              ^
list.cc:18:30: note: candidates are:
list.cc:11:3: note: A::A(std::vector<int>, int, int)
   A(std::vector<int> _nodes, int _min_version = 0, int _max_version = INT_MAX)
   ^
list.cc:6:8: note: A::A(const A&)
 struct A {
        ^
list.cc:6:8: note: A::A(A&&)

这是有道理的,有点:通用无类型列表 * 声称可以转换为任何类型;它不会(也可能不会)使用SFINAE来拒绝转换不起作用的类型。

在您的示例中,从无类型列表到A的转换比从无类型列表到std::vector<int>A的转换更好。那么转换当然不起作用。

当您传递第二个参数时,编译器知道您不可能尝试调用复制构造函数。

我个人的偏好是在构造函数中添加一个伪参数,类似于标准对piecewise_construct_t的使用:

struct from_vector { };
struct A {
  ...
  A(std::vector<int> _nodes, ...) { ... }
  A(from_vector, std::vector<int> _nodes, ...) : this(_nodes, ...) { }
};

然后你可以写

list_of<A>( from_vector(), list_of (1) (2) )

* 当我说“无类型列表”时,我当然意识到Boost实际上为该列表定义了一个类型,并且C ++表达式总是有一个类型。