Во-первых, мне жаль, если я делаю большие английские ошибки, я француз, но я стараюсь писать как можно лучше! Ну, я борюсь с C ++ 11 вариационным шаблоном. Я хочу сделать что-то немного сложнее.
Действительно, я хочу специализировать тип возвращаемого значения моего шаблона, зная, что это шаблон с переменным числом аргументов.
Моя цель — достичь чего-то вроде:
l.callFun<int>("addition", 40, 1, 1);
Специализация соответствует типу возврата, который хочет пользователь. Это привязка Lua, поэтому я не могу определить тип возвращаемого значения, если пользователь не уточнит его (очевидно, по умолчанию, если нет специализации, будет void return). Позже, это имя функции, которая вызывается в Lua. Тогда 3 целых числа соответствуют моему шаблону с вариациями.
Прямо сейчас мой шаблон выглядит так:
template <typename Z, typename T, typename... U>
Z LuaScript::callFun(const std::string& name, const T& head, const U&... tail);
Но похоже, что я не могу сделать частичную специализацию шаблонной функции. Кто-нибудь может мне помочь?
Большое спасибо!
Помощь и документация очень ценили Pheedbaq, но, наконец, я пришел с очень простым решением. Я не думал об этом таким образом, поэтому я поэкспериментирую с этим способом перегрузки операторов благодаря вам;)
Что я сделал, так это упаковал аргументы с переменными значениями и вызвал другой шаблон, специализирующийся на типе возвращаемого значения. Итак, у меня есть что-то подобное
template <typename Z, typename... T>
Z LuaScript::callFun(const std::string& name, const T&... args)
{
Z ret;
callFunReal(args);
[...]
ret = returnType<Z>();
return (ret);
}
Это было действительно довольно просто, но я не мог точно понять, как это сделать … Спасибо всем! 🙂
Решение, которое не требует изменения вашего интерфейса, заключается в переадресации вызова функции template<> class
, где вы можете специализировать на своем сердце содержание:
template<typename R, typename... Ts>
struct DoCallFun {
R operator()( LuaScript* self, std::string const& name, Ts&&... ts ) {
}
};
template <typename Z, typename... T>
Z LuaScript::callFun(const std::string& name, Ts&&... ts) {
return DoCallFun<Z, Ts...>()( this, name, head, std::forward<Ts>(ts)... )
}
и мы реализуем тело callFun
в DoCallFun
, Если ему нужен доступ к закрытым переменным в LuaScript
мы делаем DoCallFun
friend
,
Теперь лучшим решением может стать использование «черт» class
«для большей части return
тип зависимого поведения. Если вам нужно вызвать другую функцию, основанную на return
типа, вместо того, чтобы писать то же самое callFun
один раз для каждого return
типа с небольшой разницей, вы можете создать «черты» class
«где вы изолируете разницу на основе return
тип.
Предположим, вам нужно позвонить int CallAndReturnInt(...)
если тип int
а также double CallAndReturnDouble(...)
если тип double
, Вместо двух тел callFun
, напишите класс черт:
template<typename T>
struct lua_return_traits;
template<>
struct lua_return_traits<int> {
template<typename... Ts>
static int call_and_return( Ts&&... ts ) {
return CallAndReturnInt( std::forward<Ts>(ts) );
}
};
template<>
struct lua_return_traits<double> {
template<typename... Ts>
static double call_and_return( Ts&&... ts ) {
return CallAndReturnDouble( std::forward<Ts>(ts) );
}
};
и аналогичные методы для других способов ваш метод должен отличаться в зависимости от return
тип.
Идеальная переадресация начального вызова вспомогательной функции класса должна облегчить то, что вы хотите.
template<typename Z>
struct callFun_helper {
template<typename T, typename... U>
static Z help(const std::string& name, const T& head, const U&... tail) {
Z thing;
//do something with "thing"return thing;
}
};
template<typename Z, typename S, typename T, typename... U>
auto callFun(S&& s, T&& t, U&&... u)
-> decltype(callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...)) {
return callFun_helper<Z>::help(std::forward<S>(s), std::forward<T>(t), std::forward<U>(u)...);
}
//main
callFun<string>("addition", 40, 1, 1)
Ссылка ниже может помочь вам с частичной специализацией шаблона, если вы хотите узнать больше о том, что вы можете / не можете сделать с ним. Кроме того, не забудьте пометить ответ, если вы хотите продолжить получать ответы в будущем здесь, в StackOverflow 🙂