如何在模板推导中使用 ADL?

How can I use ADL in template deduction?

我有一个 class 和一个 in-class 定义的友元函数,我最好不要修改它(它来自一个已经部署的 header)

#include <numeric>
#include <vector>

namespace our_namespace {
template <typename T>
struct our_container {

  friend our_container set_union(our_container const &, our_container const &) {
    return our_container{};
  }
};
}  // namespace our_namespace

set_union 未在结构或命名空间外声明,但通常可以通过 argument-dependent 查找(c.f. Access friend function defined in class)找到。但是,我 运行 遇到了这样一种情况,我需要对函数进行未求值(即没有要求值的参数)以进行模板类型推导。更具体地说,我想将 friend 函数用作 std::accumulate:

中的二元运算
auto foo(std::vector<our_namespace::our_container<float>> in) {      
  // what I really wanted to do:
  return std::accumulate(std::next(in.begin()), in.end(), *in.begin(),
                       set_union);
}

到目前为止我发现的唯一解决方法是将函数调用包装到 lambda 中:

auto foo(std::vector<our_namespace::our_container<float>> in) {    
  // what I ended up doing:
  return std::accumulate(std::next(in.begin()), in.end(), in[0],
                       [](our_namespace::our_container<float> const& a, our_namespace::our_container<float> const& b) {return set_union(a,b);});
}

(当然我可以定义一个与 lambda 功能相同的函数)。

我试过:

除了这个 lambda,还有其他方法可以将 accumulate 与 ADL 一起使用吗?

我认为使用 lambda 是最好的方法。

正如@NathanOliver 所建议的,您可以将其缩短为:

[](auto const& a, auto const& b) {return set_union(a,b);}

如果你坚持,还有一个选择,但有点难看。

specifying the namespace for set_union (what I usually do to get around ADL, but set_union isn't in a namespace)

在命名空间中,但只能用ADL找到。

如果您在 class 之外重新声明它,您将能够通过常规查找找到它:

namespace our_namespace
{
    our_container<float> set_union(our_container<float> const &, our_container<float> const &);
}

auto foo(std::vector<our_namespace::our_container<float>> in)
{
    // what I really wanted to do:
    return std::accumulate(std::next(in.begin()), in.end(), *in.begin(),
                           our_namespace::set_union<float>);
}

遗憾的是,您不能将其声明为模板(因为它不是模板)。