ошибка: использование удаленной функции. Зачем?

Я пытаюсь создать функцию, которая применяет произвольный функтор F каждому элементу предоставленного кортежа:

#include <functional>
#include <tuple>

// apply a functor to every element of a tuple
namespace Detail {

template <std::size_t i, typename Tuple, typename F>
typename std::enable_if<i != std::tuple_size<Tuple>::value>::type
ForEachTupleImpl(Tuple& t, F& f)
{
f(std::get<i>(t));
ForEachTupleImpl<i+1>(t, f);
}

template <std::size_t i, typename Tuple, typename F>
typename std::enable_if<i == std::tuple_size<Tuple>::value>::type
ForEachTupleImpl(Tuple& t, F& f)
{
}

}

template <typename Tuple, typename F>
void ForEachTuple(Tuple& t, F& f)
{
Detail::ForEachTupleImpl<0>(t, f);
}

struct A
{
A() : a(0) {}
A(A& a) = delete;
A(const A& a) = delete;

int a;
};

int main()
{
// create a tuple of types and initialise them with zeros
using T = std::tuple<A, A, A>;
T t;

// creator a simple function object that increments the objects member
struct F
{
void operator()(A& a) const { a.a++; }
} f;

// if this works I should end up with a tuple of A's with members equal to 1
ForEachTuple(t, f);
return 0;
}

Пример живого кода: http://ideone.com/b8nLCy

Я не хочу создавать копии A потому что это может быть дорого (очевидно, в этом примере это не так), поэтому я удалил конструктор копирования. Когда я запускаю вышеуказанную программу, я получаю:

/usr/include/c++/4.8/tuple:134:25: error: use of deleted function ‘A::A(const A&)’
: _M_head_impl(__h) { }

Я знаю, что конструктор удален (это было сделано намеренно), но я не понимаю, почему он пытается сделать копии моей структуры. Почему это происходит, и как я могу добиться этого без копирования A?

1

Решение

Это проблема, вы получаете ошибку «удаленного конструктора» для:

std::function<void(A)> f = [](A& a) { a.a++; };

Вы пытаетесь настроить std::function который проходит A по значению. Но A, не имеющий конструктора копирования, не может быть передан по значению.

Попробуйте сопоставить фактический тип аргумента более тщательно:

std::function<void(A&)> f = [](A& a) { a.a++; };

Но так как вы не захватываете переменные, вы можете просто попробовать

void(*f)(A&) = [](A& a) { a.a++; };

У вас также есть серьезная проблема с базовым вариантом рекурсии шаблона: даже если вы получаете enable_if работая, что, кажется, не так, у вас будет неоднозначный вызов. Я думаю, что вам нужно также запрещать основной случай.

5

Другие решения

При создании экземпляра std::function<void(A)> функция с подписью, принимающая A по значению создается. Чтобы синтезировать это определение функции копию или ход A нужно. поскольку A не является копируемым, но не может быть перемещен, такого конструктора не существует.

Конечно, есть еще одна забавная вещь:

T t();

который объявляет функцию, возвращающую T по значению требует копию. При звонке ForEachTuple(t, f) эта функция ссылается и создается. Вы можете заменить это объявление одним из

T t;
T t{};

(в ответе выше я только посмотрел на первую обнаруженную проблему).

0

По вопросам рекламы [email protected]