Как я могу использовать ADL при выводе шаблона? - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть класс с определенной в классе функцией-другом, которую я бы в идеале не изменял (это происходит из уже развернутого заголовка)

#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:

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);
}

Единственный найденный мной обходной путь - это обернуть вызов функции в лямбду:

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);});
}

(и, разумеется, я мог бы определить функцию, которая выполняет те же функции, что и лямбда).

Я пытался:

  • указав пространство имен для set_union(что я обычно делаю, чтобы обойти ADL, но set_union не находится в пространстве имен)
  • разъясняет аргументы шаблона в set_union<our_container> (но поиск set_union не приводит к выводу аргумента шаблона изset_union, и не является шаблоном)
  • разъясняет тип set_union с …,decltype(set_union) set_union); ... за исключением того, что здесь поиск set_union завершается неудачно по той же причине и предоставляет аргументы для set_union в decltype просто вызовет его оценку и приведет к типу возвращаемого значения set_union, а не к его типу.

Есть ли другой способ использовать accumulate с ADL, чем эта лямбда

1 Ответ

0 голосов
/ 07 февраля 2019

Использование лямбды выглядит для меня лучшим способом.

Как и предположил @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>);
}

К сожалению, вы не можете объявить его как шаблон (так как это не шаблон).

...