如何在模板推导中使用ADL? [英] How can I use ADL in template deduction?
问题描述
我有一个带有类内定义的朋友函数的类,我理想上不会修改它(它来自已部署的标头)
I have a class with an in-class defined friend function that I would ideally not modify (it comes from a header that's already deployed)
#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
不在结构或名称空间之外声明,但通常可以通过依赖于参数的查找来找到(参见访问在类中定义的朋友功能)。但是,我遇到了一种情况,我需要对模板类型推导使用未经评估的函数(即无需评估参数)。更具体地说,我想在 std :: accumulate
:
set_union
is not declared outside the struct or namespace, but can normally be found through argument-dependent lookup (c.f. Access friend function defined in class). However, I ran into a situation where I need the function unevaluated (i.e. without arguments to be evaluated) for template type deduction. More specifically, I would like to use the friend function as a binary operation in 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中:
The only workaround I found so far is to wrap the function call into a 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相同的函数)。
(and of cause I could define a function that does the same as the lambda).
我尝试过:
- 指定<$的名称空间c $ c> set_union (我通常会做些什么来解决ADL,但是
set_union
不在命名空间中) - 将模板参数拼出到
set_union< our_container>
(但set_union
查找在模板中不会失败)set_union
的参数推导,并且没有模板化) - 拼写出
set_union的类型
与...,decltype(set_union)set_union);
……除外,在这里查找set_union
失败出于相同的原因,在decltype
中为set_union
提供参数只会触发其求值并返回返回类型set_union
而不是其类型。
- specifying the namespace for
set_union
(what I usually do to get around ADL, butset_union
isn't in a namespace) - spell out template arguments to
set_union<our_container>
(butset_union
lookup isn't failing at template argument deduction ofset_union
, and isn't templated itself) - spell out the type of
set_union
with…,decltype(set_union) set_union);
… except, here the lookup ofset_union
fails for the same reason, and providing arguments toset_union
in thedecltype
would just trigger its evaluation and lead to the return type ofset_union
rather than its type.
还有另一种使用积累
推荐答案
使用lambda似乎是我最好的方法。
Using a lambda looks like the best way to me.
按照@NathanOliver的建议,您可以将其缩短为:
As @NathanOliver suggested, you could shorten it to:
[](auto const& a, auto const& b) {return set_union(a,b);}
如果您坚持认为,还有另一种选择,但这有点丑陋。
If you insist, there is an alternative, but it's somewhat ugly.
指定set_union的名称空间(通常我会这样做)围绕ADL,但set_union不在名称空间中)
specifying the namespace for set_union (what I usually do to get around ADL, but set_union isn't in a namespace)
它位于,但它在名称空间中
如果在课外重新声明它,则可以通过常规查找来找到它:
If you redeclare it outside of the class, you'll be able to find it with the regular lookup:
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>);
}
不幸的是,您不能将其声明为模板(因为它不是模板模板)。
Unfortunately, you can't declare it as a template (since it's not a template).
这篇关于如何在模板推导中使用ADL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!