У меня есть набор методов с разными сигнатурами, для которых нужен один и тот же префиксный и постфиксный код, поэтому я хотел бы аккуратно обернуть каждый из них. Я пытаюсь сформулировать вариативный шаблон C ++ 14 для общей оболочки для моих функций-членов, и у меня возникают проблемы при выводе типа возвращаемого значения. auto
работает, но мне нужен возвращаемый тип явно, чтобы предоставить допустимое возвращаемое значение, даже если я поймаю исключение внутри оболочки при выполнении wrappee.
Пока мне удалось определить тип возвращаемого значения для простой функции-оболочки, используя std::result_of
, и я получил правильное поведение для нестатических функций-членов, используя auto. В течение двух дней я пытался заставить подход std::result_of
работать для функций-членов, также пробовал множество вариантов decltype()
и std::declval()
, но пока безуспешно. У меня заканчиваются идеи, как определить возвращаемый тип.
Это мой рабочий пример
#include <iostream>
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }
template<typename Fn, typename... Args>
typename std::result_of<Fn&(Args... )>::type
wrapFunc(Fn f, Args... args) {
//Do some prefix ops
typename std::result_of<Fn&(Args... )>::type ret = f(std::forward<Args>(args)...);
//Do some suffix ops
return ret;
}
class MemberWithAuto {
private:
public:
MemberWithAuto() {};
int foo(int i, int j) { return i + j;}
template<typename Fn, typename... Args>
auto wrapper(Fn f, Args... args) {
//Do some prefix ops
auto ret = (*this.*f)(std::forward<Args>(args)...);
//Do some suffix ops
return ret;
}
};
int main() {
std::cout << "FuncWrapper for foo with 1 + 2 returns " << wrapFunc<decltype(foo)>(foo, 1, 2) << std::endl;
std::cout << "FuncWrapper for bar with 'a' + 'b' * 1 returns " << wrapFunc<decltype(bar)>(bar, 'a','b', 1) << std::endl;
MemberWithAuto meau = MemberWithAuto();
std::cout << "MemberFunction with Auto with 6 + 1 returns " << meau.wrapper(&MemberWithAuto::foo, 6, 1) << std::endl;
return 0;
}
Оба они работают хорошо, но метод оболочки, использующий auto, не дает мне возвращаемого типа для дальнейшего использования. Я пробовал множество вариантов с std::result_of
и decltype()
со следующим кодом, но не могу заставить его правильно скомпилировать
#include <iostream>
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }
class MemberWithDecl {
private:
public:
MemberWithDecl() {};
int foo(int i, int j) { return i + j;}
template<typename Fn, typename... Args>
typename std::result_of<Fn&(Args... )>::type wrapper(Fn f, Args... args) {
//Do some prefix ops
typename std::result_of<Fn&(Args... )>::type ret = (*this.*f)(std::forward<Args>(args)...);
//Do some suffix ops
return ret;
}
};
int main() {
MemberWithDecl medcl = MemberWithDecl();
std::cout << "MemberFunction with declaration also works " << medcl.wrapper(&MemberWithDecl::foo, 6, 1) << std::endl;
return 0;
}
Я ожидал найти решение, в котором подпись Fn
с Args...
распознается правильно, потому что auto
также успешно определяет типы. Мое объявление типа, похоже, не находит подходящий шаблон, хотя, независимо от того, какие варианты я пробовал, я получаю
error: no matching function for call to ‘MemberWithDecl::wrapper(int (MemberWithDecl::*)(int, int), int, int)’
Если я оставлю автоматический тип возвращаемого значения оболочки и просто попробую объявить переменную ret
внутри, я получу
error: no type named ‘type’ in ‘class std::result_of<int (MemberWithDecl::*&(int, int))(int, int)>’
typename std::result_of<Fn&(Args... )>::type ret = (*this.*f)(std::forward<Args>(args)...);
После прочтения стандарта я думаю, что это означает, что result_of не считает Fn&(Args... )
правильно сформированным, но я не знаю, как должна выглядеть правильная форма.
Любая помощь приветствуется
auto
в качестве возвращаемого типа функции без конечного возвращаемого типа, вы используете C ++ 14, а не C ++ 11 - person max66   schedule 30.01.2019