我有一个带有类内定义的好友函数的类,我理想上不会修改它(它来自已部署的标头)
#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
不在结构或名称空间之外声明,但通常可以通过依赖于参数的查找(参见Access friend function defined in class)进行查找。但是,我遇到了一种情况,我需要对模板类型推导使用未经评估的函数(即无需评估参数)。更具体地说,我想在std::accumulate
中将friend函数用作二进制操作:
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相同的函数)。
我尝试过:
set_union
的名称空间(我通常会做些什么来解决ADL,但是set_union
不在名称空间中)set_union<our_container>
(但是set_union
的查找不会推论set_union
的模板参数,并且本身也没有模板化)set_union
拼写…,decltype(set_union) set_union);
的类型……,除了set_union
的查找由于相同的原因而失败,并在{{ 1}}只会触发其评估并返回set_union
的返回类型,而不是其类型。除了此lambda之外,还有其他方法可以将decltype
用于ADL吗?
答案 0 :(得分:3)
使用lambda似乎是我的最佳方法。
按照@NathanOliver的建议,您可以将其缩短为:
[](auto const& a, auto const& b) {return set_union(a,b);}
如果您坚持认为,还有另一种选择,但这有点难看。
指定set_union的名称空间(我通常会这样做以避开ADL,但set_union不在名称空间中)
它是 在命名空间中,但是只能通过ADL找到。
如果您在课程之外重新声明它,则可以通过常规查找来找到它:
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>);
}
不幸的是,您不能将其声明为模板(因为它不是模板)。