如何在模板推导中使用ADL? [英] How can I use ADL in template deduction?

查看:93
本文介绍了如何在模板推导中使用ADL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有类内定义的朋友函数的类,我理想上不会修改它(它来自已部署的标头)

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, but set_union isn't in a namespace)
  • spell out template arguments to set_union<our_container> (but set_union lookup isn't failing at template argument deduction of set_union, and isn't templated itself)
  • spell out the type of set_union with …,decltype(set_union) set_union); … except, here the lookup of set_union fails for the same reason, and providing arguments to set_union in the decltype would just trigger its evaluation and lead to the return type of set_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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆