Используйте std :: tuple для списка параметров шаблона вместо списка типов
Я пытаюсь сделать вызов шаблонной функции, как это:
typedef std::tuple<int, double, bool> InstrumentTuple;
Cache cache;
InstrumentTuple tuple = cache.get<InstrumentTuple>();
Я знаю, что могу «просто» передать типы кортежей. Это то, что я знаю, но это довольно громоздко, так как я делаю много вызовов этой функции и так как кортежи довольно длинные:
InstrumentTuple tuple = c.get<int, double, bool>(); // syntax I'd like to avoid
Поэтому я попробовал несколько реализаций метода get, но безуспешно:
Включение через параметр шаблона#include <tuple>
class Cache
{
private:
template<int I, typename T, typename = typename std::enable_if<I == std::tuple_size<T>::value>::type>
std::tuple<> get() // line 6
{
return std::tuple<>();
}
template<int I, typename T, typename = typename std::enable_if<I != std::tuple_size<T>::value>::type>
std::tuple<typename std::tuple_element<I,T>::type, decltype(get<I+1, T>())> get() // line 12
{
std::tuple<typename std::tuple_element<I,T>::type> value;
return std::tuple_cat(value, get<I+1, T>());
}
public:
template<typename T>
T get()
{
return get<0, T>(); // line 22
}
};
int main(int argc, char** argv)
{
Cache cache;
typedef std::tuple<int, double, bool> InstrumentTuple;
InstrumentTuple tuple = cache.get<InstrumentTuple>(); // line 30
}
Что дает мне эту ошибку:
main.cpp: In instantiation of 'T Cache::get() [with T = std::tuple<int, double, bool>]':
main.cpp:30:56: required from here
main.cpp:22:26: error: no matching function for call to 'Cache::get()'
main.cpp:22:26: note: candidates are:
main.cpp:6:18: note: template<int I, class T, class> std::tuple<> Cache::get()
main.cpp:6:18: note: template argument deduction/substitution failed:
main.cpp:5:33: error: no type named 'type' in 'struct std::enable_if<false, void>'
main.cpp:12:81: note: template<int I, class T, class> std::tuple<typename std::tuple_element<I, T>::type, decltype (get<(I + 1), T>())> Cache::get()
// ----- Important part
main.cpp:12:81: note: template argument deduction/substitution failed:
main.cpp: In substitution of 'template<int I, class T, class> std::tuple<typename std::tuple_element<I, T>::type, decltype (get<(I + 1), T>())> Cache::get() [with int I = 0; T = std::tuple<int, double, bool>; <template-parameter-1-3> = <missing>]':
// -----
main.cpp:22:26: required from 'T Cache::get() [with T = std::tuple<int, double, bool>]'
main.cpp:30:56: required from here
main.cpp:12:81: error: no matching function for call to 'Cache::get()'
main.cpp:12:81: note: candidate is:
main.cpp:6:18: note: template<int I, class T, class> std::tuple<> Cache::get()
main.cpp:6:18: note: template argument deduction/substitution failed:
main.cpp:5:33: error: no type named 'type' in 'struct std::enable_if<false, void>'
main.cpp: In instantiation of 'T Cache::get() [with T = std::tuple<int, double, bool>]':
main.cpp:30:56: required from here
main.cpp:20:7: note: template<class T> T Cache::get()
main.cpp:20:7: note: template argument deduction/substitution failed:
main.cpp:22:26: error: wrong number of template arguments (2, should be 1)
Я не понимаю, почему отсутствует параметр шаблона.
Поэтому я попробовал другую реализацию:
Шаблон-шаблон с именем параметра#include <tuple>
class Cache
{
private:
template<int>
std::tuple<> get() // line 7
{
return std::tuple<>();
}
template<int index, typename type, typename... rest>
std::tuple<type, rest...> get() // line 13
{
return std::tuple_cat(std::tuple<type>(), get<index+1, rest...>());
}
public:
template<template<typename... types> class tuple>
typename std::tuple<(tuple::types)...> get()
{
return get<0, (tuple::types)...>();
}
}; // line 24
int main(int argc, char** argv)
{
Cache cache;
typedef std::tuple<int, double, bool> InstrumentTuple;
InstrumentTuple tuple = cache.get<InstrumentTuple>(); // line 30
}
Но тогда я получаю эту ошибку:
// ----- Important part
main.cpp:24:1: error: expected identifier before '}' token
main.cpp:24:1: error: expected unqualified-id before '}' token
// -----
main.cpp: In function 'int main(int, char**)':
main.cpp:30:56: error: no matching function for call to 'Cache::get()'
main.cpp:30:56: note: candidates are:
main.cpp:7:18: note: template<int <anonymous> > std::tuple<> Cache::get()
main.cpp:7:18: note: template argument deduction/substitution failed:
main.cpp:13:31: note: template<int index, class type, class ... rest> std::tuple<_Head, _Tail ...> Cache::get()
main.cpp:13:31: note: template argument deduction/substitution failed:
Опять же, я не понимаю ошибки из-за отсутствия идентификатора.
Теперь мне интересно, возможно ли то, чего я хочу достичь. Можно ли использоватьstd::tuple
как я хочу? Или есть лучший способ?