将'using std :: foo'指令应用于本地构造函数初始化列表(C++)

mar*_*ack 13 c++ using using-directives c++11

给定一个自定义类型,下面的片段显示了允许函数自动选择特定于该类型的用户提供的重载的常用方法,或者如果没有,则显示标准库中的函数的泛型实现.

// assume std::foo is a real function template returning an int
namespace a {
  struct b { };    
  int foo(b& ab) { ... }
}

int bar(a::b& ab)
{
  using std::foo;
  return foo(ab);
}
Run Code Online (Sandbox Code Playgroud)

这种方法会自动选择a::foo优先于std::foo(如果存在).

我的问题是,当有问题的调用是构造函数初始化列表的一部分时,是否有可能实现类似的行为?

struct bar2
{
  bar2(a::b& ab);
  int i;
};

bar2::bar2(a::b& ab)
  : i{foo(ab)} // want a::foo if available, else std::foo
{ }
Run Code Online (Sandbox Code Playgroud)

显然,放入using std::foo构造函数体内为时已晚.但是,如果我把它放在构造函数定义之前,我会引入std::foo全局命名空间,这也是不可取的.

在这种情况下,有没有办法让两全其美?

小智 5

根据Can,using语句出现在构造函数初始化列表中?一个解决方法是使用像这样的私有静态函数:

struct bar2
{
  bar2(a::b& ab);
  int i;
  private:
  static int wrapper(a::b& f)
  {
      using std::foo;
      return foo(f);
  }
};

bar2::bar2(a::b& ab)
  : i{wrapper(ab)} // want a::foo if available, else std::foo
{ }
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以保留初始化列表的好处,而无需将初始化移动到构造函数的主体.上面链接的问题中的OP声称它不提供ADL,但它似乎对我有用.要测试,只需删除:

int bar(foo f)
{
    std::cout << "custom.\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 你也可以用lambda来保持接近:`bar2 :: bar2(a :: b&ab):i {[&] {using std :: foo; return foo(ab); }()} {}` (2认同)
  • 我会接受这个答案,虽然我可能更喜欢lambda技巧@ galop1n建议,因为它保持黑客本地.我们不得不求助于这样的愚蠢的事情来解决名称查找问题,这有点遗憾. (2认同)