#c #templates #vector #c 14
Вопрос:
Я пытаюсь вызвать функцию обратного вызова из шаблонной функции. Но аргументы функции обратного вызова зависят от switch
оператора.
Вот рабочий код, который объясняет, что я собираюсь сделать, используя игрушечный пример.
#include <vector>
struct A {};
struct B {};
struct C {};
struct D {};
enum class StructType
{
A,
B,
C,
D
};
std::vector<A> vec_A;
std::vector<B> vec_B;
std::vector<C> vec_C;
std::vector<D> vec_D;
template <template <class> class Container, class ValueType>
void process(const StructTypeamp; struct_type)
{
auto callback = [amp;](Container<ValueType>amp; v) {};
switch(struct_type)
{
case StructType::A:
callback(vec_A);
break;
case StructType::B:
callback(vec_B);
break;
case StructType::C:
callback(vec_C);
break;
case StructType::D:
callback(vec_D);
break;
}
}
int main()
{
process<std::vector, A>(StructType::A);
}
При компиляции я получаю следующую ошибку:
$ g template.cpp
template.cpp: In instantiation of ‘void process(const StructTypeamp;) [with Iterator = std::vector; ValueType = A]’:
template.cpp:47:26: required from here
template.cpp:33:15: error: no match for call to ‘(process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>) (std::vector<B>amp;)’
33 | callback(vec_B);
| ~~~~~~~~^~~~~~~
template.cpp:25:19: note: candidate: ‘process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>’
25 | auto callback = [amp;](Iterator<ValueType>amp; v) {};
| ^
template.cpp:25:19: note: no known conversion for argument 1 from ‘std::vector<B>’ to ‘std::vector<A>amp;’
template.cpp:36:15: error: no match for call to ‘(process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>) (std::vector<C>amp;)’
36 | callback(vec_C);
| ~~~~~~~~^~~~~~~
template.cpp:25:19: note: candidate: ‘process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>’
25 | auto callback = [amp;](Iterator<ValueType>amp; v) {};
| ^
template.cpp:25:19: note: no known conversion for argument 1 from ‘std::vector<C>’ to ‘std::vector<A>amp;’
template.cpp:39:15: error: no match for call to ‘(process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>) (std::vector<D>amp;)’
39 | callback(vec_D);
| ~~~~~~~~^~~~~~~
template.cpp:25:19: note: candidate: ‘process<std::vector, A>(const StructTypeamp;)::<lambda(std::vector<A>amp;)>’
25 | auto callback = [amp;](Iterator<ValueType>amp; v) {};
| ^
template.cpp:25:19: note: no known conversion for argument 1 from ‘std::vector<D>’ to ‘std::vector<A>amp;’
Моя g
версия такова: 11.1.0
.
Я могу понять ошибку, но просто не знаю, как это исправить.
Мы будем очень признательны за любую помощь. Спасибо.
ПРАВКА 1: Iterator
-> > Container
для типа шаблона имеет больше смысла, как предложил @Ted Lyngmo.
Комментарии:
1. У вас есть аргумент функции, который известен только во время выполнения, но он зависит от типа времени компиляции в параметре шаблона. Вам действительно нужен аргумент времени выполнения в этом случае? Пример Не связан:
Iterator
это странное имя для параметра шаблона.Container
может быть, это подойдет лучше.2. Итак, ты предлагаешь мне просто использовать
auto callback = [amp;](const autoamp; v) {};
? Потому что это не компилируется с использованием-std=c 14
флага.3. Я задаюсь вопросом, почему вы должны снабжать
StructType::A
process
кого-то . Что должно произойти, если вы позвоните сprocess<std::vector, A>(StructType::B);
этим ?4. Это был всего лишь игрушечный пример. В реальной реализации
process
вызывается с различными типамиStruct
, я просто хотел смоделировать это поведение здесь , используяStruct::A
в качестве примера. Или, скорее, скажем, процесс передается с контейнером, который содержит различные типы векторных данных, которые вызываютcallback
.5. Итак, из аргумента функции
StructType::A
вы знаете, что она должна использовать astd::vector<A>
— но эта информация уже содержится в параметрах шаблона (как я показал в своем примере вверху). Я все еще не вижу причины для предоставления той же информации с помощью аргумента времени выполнения.
Ответ №1:
Как говорят ваши ошибки, нет совпадений для callback
функторов, которые вы не создали.
Я предлагаю удалить аргумент времени выполнения process
и использовать информацию, которую вы имеете только в параметрах шаблона функции.
Пример:
#include <vector>
#include <type_traits>
struct A {};
struct B {};
struct C {};
struct D {};
// enum class StructType {A, B, C, D }; // perhaps not needed anymore
std::vector<A> vec_A;
std::vector<B> vec_B;
std::vector<C> vec_C;
std::vector<D> vec_D;
template<class T> autoamp; get_vec();
template<> autoamp; get_vec<std::vector<A>>() { return vec_A; }
template<> autoamp; get_vec<std::vector<B>>() { return vec_B; }
template<> autoamp; get_vec<std::vector<C>>() { return vec_C; }
template<> autoamp; get_vec<std::vector<D>>() { return vec_D; }
template <template <class, class...> class Container, class ValueType>
void process() {
using container_type = Container<ValueType>;
auto callback = [amp;](container_typeamp;) {};
callback(get_vec<container_type>());
}
int main() {
process<std::vector, A>();
}